mirror of
https://github.com/postgres/postgres.git
synced 2025-10-16 17:07:43 +03:00
Remove dashes in comments that don't need them, rewrap with pgindent.
This commit is contained in:
@@ -15,7 +15,7 @@
|
||||
* ExecInitTee
|
||||
* ExecEndTee
|
||||
*
|
||||
* $Id: nodeTee.c,v 1.9 2001/01/24 19:42:55 momjian Exp $
|
||||
* $Id: nodeTee.c,v 1.10 2001/03/22 06:16:13 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -60,9 +60,8 @@ ExecInitTee(Tee * node, EState *currentEstate, Plan *parent)
|
||||
if (node->plan.state)
|
||||
return TRUE;
|
||||
|
||||
/* ----------------
|
||||
* assign the node's execution state
|
||||
* ----------------
|
||||
/*
|
||||
* assign the node's execution state
|
||||
*/
|
||||
|
||||
/*
|
||||
@@ -93,9 +92,8 @@ ExecInitTee(Tee * node, EState *currentEstate, Plan *parent)
|
||||
node->plan.state = estate;
|
||||
|
||||
|
||||
/* ----------------
|
||||
/*
|
||||
* create teeState structure
|
||||
* ----------------
|
||||
*/
|
||||
teeState = makeNode(TeeState);
|
||||
teeState->tee_leftPlace = 0;
|
||||
@@ -120,9 +118,9 @@ ExecInitTee(Tee * node, EState *currentEstate, Plan *parent)
|
||||
ExecAssignExprContext(estate, &(teeState->cstate));
|
||||
|
||||
#define TEE_NSLOTS 2
|
||||
/* ----------------
|
||||
* initialize tuple slots
|
||||
* ----------------
|
||||
|
||||
/*
|
||||
* initialize tuple slots
|
||||
*/
|
||||
ExecInitResultTupleSlot(estate, &(teeState->cstate));
|
||||
|
||||
@@ -130,16 +128,16 @@ ExecInitTee(Tee * node, EState *currentEstate, Plan *parent)
|
||||
outerPlan = outerPlan((Plan *) node);
|
||||
ExecInitNode(outerPlan, estate, (Plan *) node);
|
||||
|
||||
/* ----------------
|
||||
* the tuple type info is from the outer plan of this node
|
||||
* the result type is also the same as the outerplan
|
||||
/*
|
||||
* the tuple type info is from the outer plan of this node the result
|
||||
* type is also the same as the outerplan
|
||||
*/
|
||||
ExecAssignResultTypeFromOuterPlan((Plan *) node, &(teeState->cstate));
|
||||
ExecAssignProjectionInfo((Plan *) node, &teeState->cstate);
|
||||
|
||||
/* ---------------------------------------
|
||||
initialize temporary relation to buffer tuples
|
||||
*/
|
||||
/*
|
||||
* initialize temporary relation to buffer tuples
|
||||
*/
|
||||
tupType = ExecGetResultType(&(teeState->cstate));
|
||||
len = ExecTargetListLength(((Plan *) node)->targetlist);
|
||||
|
||||
|
@@ -6,7 +6,7 @@
|
||||
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: execAmi.c,v 1.57 2001/03/22 03:59:25 momjian Exp $
|
||||
* $Id: execAmi.c,v 1.58 2001/03/22 06:16:12 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -78,23 +78,20 @@ ExecOpenScanR(Oid relOid,
|
||||
Relation relation;
|
||||
Pointer scanDesc;
|
||||
|
||||
/* ----------------
|
||||
* note: scanDesc returned by ExecBeginScan can be either
|
||||
* a HeapScanDesc or an IndexScanDesc so for now we
|
||||
* make it a Pointer. There should be a better scan
|
||||
* abstraction someday -cim 9/9/89
|
||||
* ----------------
|
||||
/*
|
||||
* note: scanDesc returned by ExecBeginScan can be either a
|
||||
* HeapScanDesc or an IndexScanDesc so for now we make it a Pointer.
|
||||
* There should be a better scan abstraction someday -cim 9/9/89
|
||||
*/
|
||||
|
||||
/* ----------------
|
||||
* Open the relation with the correct call depending
|
||||
* on whether this is a heap relation or an index relation.
|
||||
/*
|
||||
* Open the relation with the correct call depending on whether this
|
||||
* is a heap relation or an index relation.
|
||||
*
|
||||
* For a table, acquire AccessShareLock for the duration of the query
|
||||
* execution. For indexes, acquire no lock here; the index machinery
|
||||
* does its own locks and unlocks. (We rely on having some kind of
|
||||
* lock on the parent table to ensure the index won't go away!)
|
||||
* ----------------
|
||||
* For a table, acquire AccessShareLock for the duration of the query
|
||||
* execution. For indexes, acquire no lock here; the index machinery
|
||||
* does its own locks and unlocks. (We rely on having some kind of
|
||||
* lock on the parent table to ensure the index won't go away!)
|
||||
*/
|
||||
if (isindex)
|
||||
relation = index_open(relOid);
|
||||
@@ -136,13 +133,12 @@ ExecBeginScan(Relation relation,
|
||||
{
|
||||
Pointer scanDesc;
|
||||
|
||||
/* ----------------
|
||||
* open the appropriate type of scan.
|
||||
/*
|
||||
* open the appropriate type of scan.
|
||||
*
|
||||
* Note: ambeginscan()'s second arg is a boolean indicating
|
||||
* that the scan should be done in reverse.. That is,
|
||||
* if you pass it true, then the scan is backward.
|
||||
* ----------------
|
||||
* Note: ambeginscan()'s second arg is a boolean indicating that the scan
|
||||
* should be done in reverse.. That is, if you pass it true, then the
|
||||
* scan is backward.
|
||||
*/
|
||||
if (isindex)
|
||||
{
|
||||
@@ -180,9 +176,8 @@ ExecCloseR(Plan *node)
|
||||
Relation relation;
|
||||
HeapScanDesc scanDesc;
|
||||
|
||||
/* ----------------
|
||||
* get state for node and shut down the heap scan, if any
|
||||
* ----------------
|
||||
/*
|
||||
* get state for node and shut down the heap scan, if any
|
||||
*/
|
||||
switch (nodeTag(node))
|
||||
{
|
||||
@@ -209,10 +204,9 @@ ExecCloseR(Plan *node)
|
||||
if (scanDesc != NULL)
|
||||
heap_endscan(scanDesc);
|
||||
|
||||
/* ----------------
|
||||
* if this is an index scan then we have to take care
|
||||
* of the index relations as well.
|
||||
* ----------------
|
||||
/*
|
||||
* if this is an index scan then we have to take care of the index
|
||||
* relations as well.
|
||||
*/
|
||||
if (IsA(node, IndexScan))
|
||||
{
|
||||
@@ -229,10 +223,10 @@ ExecCloseR(Plan *node)
|
||||
|
||||
for (i = 0; i < numIndices; i++)
|
||||
{
|
||||
/* ----------------
|
||||
* shut down each of the index scans and
|
||||
* close each of the index relations
|
||||
* ----------------
|
||||
|
||||
/*
|
||||
* shut down each of the index scans and close each of the
|
||||
* index relations
|
||||
*/
|
||||
if (indexScanDescs[i] != NULL)
|
||||
index_endscan(indexScanDescs[i]);
|
||||
|
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/execJunk.c,v 1.26 2001/03/22 03:59:26 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/execJunk.c,v 1.27 2001/03/22 06:16:12 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -90,12 +90,10 @@ ExecInitJunkFilter(List *targetList, TupleDesc tupType)
|
||||
ALLOCSET_DEFAULT_MAXSIZE);
|
||||
oldContext = MemoryContextSwitchTo(junkContext);
|
||||
|
||||
/* ---------------------
|
||||
* First find the "clean" target list, i.e. all the entries
|
||||
* in the original target list which have a false 'resjunk'
|
||||
* NOTE: make copy of the Resdom nodes, because we have
|
||||
* to change the 'resno's...
|
||||
* ---------------------
|
||||
/*
|
||||
* First find the "clean" target list, i.e. all the entries in the
|
||||
* original target list which have a false 'resjunk' NOTE: make copy
|
||||
* of the Resdom nodes, because we have to change the 'resno's...
|
||||
*/
|
||||
cleanTargetList = NIL;
|
||||
cleanResno = 1;
|
||||
@@ -167,25 +165,23 @@ ExecInitJunkFilter(List *targetList, TupleDesc tupType)
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------
|
||||
/*
|
||||
* Now calculate the tuple type for the cleaned tuple (we were already
|
||||
* given the type for the original targetlist).
|
||||
* ---------------------
|
||||
*/
|
||||
cleanTupType = ExecTypeFromTL(cleanTargetList);
|
||||
|
||||
len = ExecTargetListLength(targetList);
|
||||
cleanLength = ExecTargetListLength(cleanTargetList);
|
||||
|
||||
/* ---------------------
|
||||
* Now calculate the "map" between the original tuple's attributes
|
||||
* and the "clean" tuple's attributes.
|
||||
/*
|
||||
* Now calculate the "map" between the original tuple's attributes and
|
||||
* the "clean" tuple's attributes.
|
||||
*
|
||||
* The "map" is an array of "cleanLength" attribute numbers, i.e.
|
||||
* one entry for every attribute of the "clean" tuple.
|
||||
* The value of this entry is the attribute number of the corresponding
|
||||
* attribute of the "original" tuple.
|
||||
* ---------------------
|
||||
* The "map" is an array of "cleanLength" attribute numbers, i.e. one
|
||||
* entry for every attribute of the "clean" tuple. The value of this
|
||||
* entry is the attribute number of the corresponding attribute of the
|
||||
* "original" tuple.
|
||||
*/
|
||||
if (cleanLength > 0)
|
||||
{
|
||||
@@ -236,9 +232,8 @@ ExecInitJunkFilter(List *targetList, TupleDesc tupType)
|
||||
else
|
||||
cleanMap = NULL;
|
||||
|
||||
/* ---------------------
|
||||
/*
|
||||
* Finally create and initialize the JunkFilter struct.
|
||||
* ---------------------
|
||||
*/
|
||||
junkfilter = makeNode(JunkFilter);
|
||||
|
||||
@@ -298,10 +293,9 @@ ExecGetJunkAttribute(JunkFilter *junkfilter,
|
||||
TupleDesc tupType;
|
||||
HeapTuple tuple;
|
||||
|
||||
/* ---------------------
|
||||
* first look in the junkfilter's target list for
|
||||
* an attribute with the given name
|
||||
* ---------------------
|
||||
/*
|
||||
* first look in the junkfilter's target list for an attribute with
|
||||
* the given name
|
||||
*/
|
||||
resno = InvalidAttrNumber;
|
||||
targetList = junkfilter->jf_targetList;
|
||||
@@ -327,9 +321,8 @@ ExecGetJunkAttribute(JunkFilter *junkfilter,
|
||||
return false;
|
||||
}
|
||||
|
||||
/* ---------------------
|
||||
/*
|
||||
* Now extract the attribute value from the tuple.
|
||||
* ---------------------
|
||||
*/
|
||||
tuple = slot->val;
|
||||
tupType = junkfilter->jf_tupType;
|
||||
@@ -361,9 +354,8 @@ ExecRemoveJunk(JunkFilter *junkfilter, TupleTableSlot *slot)
|
||||
Datum values_array[64];
|
||||
char nulls_array[64];
|
||||
|
||||
/* ----------------
|
||||
* get info from the slot and the junk filter
|
||||
* ----------------
|
||||
/*
|
||||
* get info from the slot and the junk filter
|
||||
*/
|
||||
tuple = slot->val;
|
||||
|
||||
@@ -372,21 +364,19 @@ ExecRemoveJunk(JunkFilter *junkfilter, TupleTableSlot *slot)
|
||||
cleanLength = junkfilter->jf_cleanLength;
|
||||
cleanMap = junkfilter->jf_cleanMap;
|
||||
|
||||
/* ---------------------
|
||||
* Handle the trivial case first.
|
||||
* ---------------------
|
||||
/*
|
||||
* Handle the trivial case first.
|
||||
*/
|
||||
if (cleanLength == 0)
|
||||
return (HeapTuple) NULL;
|
||||
|
||||
/* ---------------------
|
||||
* Create the arrays that will hold the attribute values
|
||||
* and the null information for the new "clean" tuple.
|
||||
/*
|
||||
* Create the arrays that will hold the attribute values and the null
|
||||
* information for the new "clean" tuple.
|
||||
*
|
||||
* Note: we use memory on the stack to optimize things when
|
||||
* we are dealing with a small number of tuples.
|
||||
* for large tuples we just use palloc.
|
||||
* ---------------------
|
||||
* Note: we use memory on the stack to optimize things when we are
|
||||
* dealing with a small number of tuples. for large tuples we just use
|
||||
* palloc.
|
||||
*/
|
||||
if (cleanLength > 64)
|
||||
{
|
||||
@@ -399,9 +389,8 @@ ExecRemoveJunk(JunkFilter *junkfilter, TupleTableSlot *slot)
|
||||
nulls = nulls_array;
|
||||
}
|
||||
|
||||
/* ---------------------
|
||||
/*
|
||||
* Exctract one by one all the values of the "clean" tuple.
|
||||
* ---------------------
|
||||
*/
|
||||
for (i = 0; i < cleanLength; i++)
|
||||
{
|
||||
@@ -413,18 +402,16 @@ ExecRemoveJunk(JunkFilter *junkfilter, TupleTableSlot *slot)
|
||||
nulls[i] = ' ';
|
||||
}
|
||||
|
||||
/* ---------------------
|
||||
/*
|
||||
* Now form the new tuple.
|
||||
* ---------------------
|
||||
*/
|
||||
cleanTuple = heap_formtuple(cleanTupType,
|
||||
values,
|
||||
nulls);
|
||||
|
||||
/* ---------------------
|
||||
* We are done. Free any space allocated for 'values' and 'nulls'
|
||||
* and return the new tuple.
|
||||
* ---------------------
|
||||
/*
|
||||
* We are done. Free any space allocated for 'values' and 'nulls' and
|
||||
* return the new tuple.
|
||||
*/
|
||||
if (cleanLength > 64)
|
||||
{
|
||||
|
@@ -12,7 +12,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/execProcnode.c,v 1.25 2001/01/29 00:39:18 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/execProcnode.c,v 1.26 2001/03/22 06:16:12 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -117,10 +117,8 @@ ExecInitNode(Plan *node, EState *estate, Plan *parent)
|
||||
bool result;
|
||||
List *subp;
|
||||
|
||||
/* ----------------
|
||||
* do nothing when we get to the end
|
||||
* of a leaf on tree.
|
||||
* ----------------
|
||||
/*
|
||||
* do nothing when we get to the end of a leaf on tree.
|
||||
*/
|
||||
if (node == NULL)
|
||||
return FALSE;
|
||||
@@ -134,9 +132,9 @@ ExecInitNode(Plan *node, EState *estate, Plan *parent)
|
||||
|
||||
switch (nodeTag(node))
|
||||
{
|
||||
/* ----------------
|
||||
* control nodes
|
||||
* ----------------
|
||||
|
||||
/*
|
||||
* control nodes
|
||||
*/
|
||||
case T_Result:
|
||||
result = ExecInitResult((Result *) node, estate, parent);
|
||||
@@ -146,9 +144,8 @@ ExecInitNode(Plan *node, EState *estate, Plan *parent)
|
||||
result = ExecInitAppend((Append *) node, estate, parent);
|
||||
break;
|
||||
|
||||
/* ----------------
|
||||
* scan nodes
|
||||
* ----------------
|
||||
/*
|
||||
* scan nodes
|
||||
*/
|
||||
case T_SeqScan:
|
||||
result = ExecInitSeqScan((SeqScan *) node, estate, parent);
|
||||
@@ -167,9 +164,8 @@ ExecInitNode(Plan *node, EState *estate, Plan *parent)
|
||||
parent);
|
||||
break;
|
||||
|
||||
/* ----------------
|
||||
* join nodes
|
||||
* ----------------
|
||||
/*
|
||||
* join nodes
|
||||
*/
|
||||
case T_NestLoop:
|
||||
result = ExecInitNestLoop((NestLoop *) node, estate, parent);
|
||||
@@ -187,9 +183,8 @@ ExecInitNode(Plan *node, EState *estate, Plan *parent)
|
||||
result = ExecInitHashJoin((HashJoin *) node, estate, parent);
|
||||
break;
|
||||
|
||||
/* ----------------
|
||||
* materialization nodes
|
||||
* ----------------
|
||||
/*
|
||||
* materialization nodes
|
||||
*/
|
||||
case T_Material:
|
||||
result = ExecInitMaterial((Material *) node, estate, parent);
|
||||
@@ -253,9 +248,8 @@ ExecProcNode(Plan *node, Plan *parent)
|
||||
|
||||
CHECK_FOR_INTERRUPTS();
|
||||
|
||||
/* ----------------
|
||||
* deal with NULL nodes..
|
||||
* ----------------
|
||||
/*
|
||||
* deal with NULL nodes..
|
||||
*/
|
||||
if (node == NULL)
|
||||
return NULL;
|
||||
@@ -265,9 +259,9 @@ ExecProcNode(Plan *node, Plan *parent)
|
||||
|
||||
switch (nodeTag(node))
|
||||
{
|
||||
/* ----------------
|
||||
* control nodes
|
||||
* ----------------
|
||||
|
||||
/*
|
||||
* control nodes
|
||||
*/
|
||||
case T_Result:
|
||||
result = ExecResult((Result *) node);
|
||||
@@ -277,9 +271,8 @@ ExecProcNode(Plan *node, Plan *parent)
|
||||
result = ExecProcAppend((Append *) node);
|
||||
break;
|
||||
|
||||
/* ----------------
|
||||
* scan nodes
|
||||
* ----------------
|
||||
/*
|
||||
* scan nodes
|
||||
*/
|
||||
case T_SeqScan:
|
||||
result = ExecSeqScan((SeqScan *) node);
|
||||
@@ -297,9 +290,8 @@ ExecProcNode(Plan *node, Plan *parent)
|
||||
result = ExecSubqueryScan((SubqueryScan *) node);
|
||||
break;
|
||||
|
||||
/* ----------------
|
||||
* join nodes
|
||||
* ----------------
|
||||
/*
|
||||
* join nodes
|
||||
*/
|
||||
case T_NestLoop:
|
||||
result = ExecNestLoop((NestLoop *) node);
|
||||
@@ -317,9 +309,8 @@ ExecProcNode(Plan *node, Plan *parent)
|
||||
result = ExecHashJoin((HashJoin *) node);
|
||||
break;
|
||||
|
||||
/* ----------------
|
||||
* materialization nodes
|
||||
* ----------------
|
||||
/*
|
||||
* materialization nodes
|
||||
*/
|
||||
case T_Material:
|
||||
result = ExecMaterial((Material *) node);
|
||||
@@ -366,9 +357,9 @@ ExecCountSlotsNode(Plan *node)
|
||||
|
||||
switch (nodeTag(node))
|
||||
{
|
||||
/* ----------------
|
||||
* control nodes
|
||||
* ----------------
|
||||
|
||||
/*
|
||||
* control nodes
|
||||
*/
|
||||
case T_Result:
|
||||
return ExecCountSlotsResult((Result *) node);
|
||||
@@ -376,9 +367,8 @@ ExecCountSlotsNode(Plan *node)
|
||||
case T_Append:
|
||||
return ExecCountSlotsAppend((Append *) node);
|
||||
|
||||
/* ----------------
|
||||
* scan nodes
|
||||
* ----------------
|
||||
/*
|
||||
* scan nodes
|
||||
*/
|
||||
case T_SeqScan:
|
||||
return ExecCountSlotsSeqScan((SeqScan *) node);
|
||||
@@ -392,9 +382,8 @@ ExecCountSlotsNode(Plan *node)
|
||||
case T_SubqueryScan:
|
||||
return ExecCountSlotsSubqueryScan((SubqueryScan *) node);
|
||||
|
||||
/* ----------------
|
||||
* join nodes
|
||||
* ----------------
|
||||
/*
|
||||
* join nodes
|
||||
*/
|
||||
case T_NestLoop:
|
||||
return ExecCountSlotsNestLoop((NestLoop *) node);
|
||||
@@ -408,9 +397,8 @@ ExecCountSlotsNode(Plan *node)
|
||||
case T_HashJoin:
|
||||
return ExecCountSlotsHashJoin((HashJoin *) node);
|
||||
|
||||
/* ----------------
|
||||
* materialization nodes
|
||||
* ----------------
|
||||
/*
|
||||
* materialization nodes
|
||||
*/
|
||||
case T_Material:
|
||||
return ExecCountSlotsMaterial((Material *) node);
|
||||
@@ -457,10 +445,8 @@ ExecEndNode(Plan *node, Plan *parent)
|
||||
{
|
||||
List *subp;
|
||||
|
||||
/* ----------------
|
||||
* do nothing when we get to the end
|
||||
* of a leaf on tree.
|
||||
* ----------------
|
||||
/*
|
||||
* do nothing when we get to the end of a leaf on tree.
|
||||
*/
|
||||
if (node == NULL)
|
||||
return;
|
||||
@@ -477,9 +463,9 @@ ExecEndNode(Plan *node, Plan *parent)
|
||||
|
||||
switch (nodeTag(node))
|
||||
{
|
||||
/* ----------------
|
||||
* control nodes
|
||||
* ----------------
|
||||
|
||||
/*
|
||||
* control nodes
|
||||
*/
|
||||
case T_Result:
|
||||
ExecEndResult((Result *) node);
|
||||
@@ -489,9 +475,8 @@ ExecEndNode(Plan *node, Plan *parent)
|
||||
ExecEndAppend((Append *) node);
|
||||
break;
|
||||
|
||||
/* ----------------
|
||||
* scan nodes
|
||||
* ----------------
|
||||
/*
|
||||
* scan nodes
|
||||
*/
|
||||
case T_SeqScan:
|
||||
ExecEndSeqScan((SeqScan *) node);
|
||||
@@ -509,9 +494,8 @@ ExecEndNode(Plan *node, Plan *parent)
|
||||
ExecEndSubqueryScan((SubqueryScan *) node);
|
||||
break;
|
||||
|
||||
/* ----------------
|
||||
* join nodes
|
||||
* ----------------
|
||||
/*
|
||||
* join nodes
|
||||
*/
|
||||
case T_NestLoop:
|
||||
ExecEndNestLoop((NestLoop *) node);
|
||||
@@ -529,9 +513,8 @@ ExecEndNode(Plan *node, Plan *parent)
|
||||
ExecEndHashJoin((HashJoin *) node);
|
||||
break;
|
||||
|
||||
/* ----------------
|
||||
* materialization nodes
|
||||
* ----------------
|
||||
/*
|
||||
* materialization nodes
|
||||
*/
|
||||
case T_Material:
|
||||
ExecEndMaterial((Material *) node);
|
||||
@@ -726,9 +709,9 @@ ExecGetTupType(Plan *node)
|
||||
break;
|
||||
|
||||
default:
|
||||
/* ----------------
|
||||
* should never get here
|
||||
* ----------------
|
||||
|
||||
/*
|
||||
* should never get here
|
||||
*/
|
||||
elog(ERROR, "ExecGetTupType: node type %d unsupported",
|
||||
(int) nodeTag(node));
|
||||
|
@@ -12,7 +12,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/execScan.c,v 1.16 2001/03/22 03:59:26 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/execScan.c,v 1.17 2001/03/22 06:16:12 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -55,20 +55,18 @@ ExecScan(Scan *node,
|
||||
ExprDoneCond isDone;
|
||||
TupleTableSlot *resultSlot;
|
||||
|
||||
/* ----------------
|
||||
* Fetch data from node
|
||||
* ----------------
|
||||
/*
|
||||
* Fetch data from node
|
||||
*/
|
||||
estate = node->plan.state;
|
||||
scanstate = node->scanstate;
|
||||
econtext = scanstate->cstate.cs_ExprContext;
|
||||
qual = node->plan.qual;
|
||||
|
||||
/* ----------------
|
||||
* Check to see if we're still projecting out tuples from a previous
|
||||
* scan tuple (because there is a function-returning-set in the
|
||||
* projection expressions). If so, try to project another one.
|
||||
* ----------------
|
||||
/*
|
||||
* Check to see if we're still projecting out tuples from a previous
|
||||
* scan tuple (because there is a function-returning-set in the
|
||||
* projection expressions). If so, try to project another one.
|
||||
*/
|
||||
if (scanstate->cstate.cs_TupFromTlist)
|
||||
{
|
||||
@@ -79,11 +77,10 @@ ExecScan(Scan *node,
|
||||
scanstate->cstate.cs_TupFromTlist = false;
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* Reset per-tuple memory context to free any expression evaluation
|
||||
* storage allocated in the previous tuple cycle. Note this can't
|
||||
* happen until we're done projecting out tuples from a scan tuple.
|
||||
* ----------------
|
||||
/*
|
||||
* Reset per-tuple memory context to free any expression evaluation
|
||||
* storage allocated in the previous tuple cycle. Note this can't
|
||||
* happen until we're done projecting out tuples from a scan tuple.
|
||||
*/
|
||||
ResetExprContext(econtext);
|
||||
|
||||
@@ -97,12 +94,11 @@ ExecScan(Scan *node,
|
||||
|
||||
slot = (*accessMtd) (node);
|
||||
|
||||
/* ----------------
|
||||
* if the slot returned by the accessMtd contains
|
||||
* NULL, then it means there is nothing more to scan
|
||||
* so we just return an empty slot, being careful to use
|
||||
* the projection result slot so it has correct tupleDesc.
|
||||
* ----------------
|
||||
/*
|
||||
* if the slot returned by the accessMtd contains NULL, then it
|
||||
* means there is nothing more to scan so we just return an empty
|
||||
* slot, being careful to use the projection result slot so it has
|
||||
* correct tupleDesc.
|
||||
*/
|
||||
if (TupIsNull(slot))
|
||||
{
|
||||
@@ -112,29 +108,27 @@ ExecScan(Scan *node,
|
||||
true);
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* place the current tuple into the expr context
|
||||
* ----------------
|
||||
/*
|
||||
* place the current tuple into the expr context
|
||||
*/
|
||||
econtext->ecxt_scantuple = slot;
|
||||
|
||||
/* ----------------
|
||||
* check that the current tuple satisfies the qual-clause
|
||||
/*
|
||||
* check that the current tuple satisfies the qual-clause
|
||||
*
|
||||
* check for non-nil qual here to avoid a function call to
|
||||
* ExecQual() when the qual is nil ... saves only a few cycles,
|
||||
* but they add up ...
|
||||
* ----------------
|
||||
* check for non-nil qual here to avoid a function call to ExecQual()
|
||||
* when the qual is nil ... saves only a few cycles, but they add
|
||||
* up ...
|
||||
*/
|
||||
if (!qual || ExecQual(qual, econtext, false))
|
||||
{
|
||||
/* ----------------
|
||||
* Found a satisfactory scan tuple.
|
||||
|
||||
/*
|
||||
* Found a satisfactory scan tuple.
|
||||
*
|
||||
* Form a projection tuple, store it in the result tuple
|
||||
* slot and return it --- unless we find we can project no
|
||||
* tuples from this scan tuple, in which case continue scan.
|
||||
* ----------------
|
||||
* Form a projection tuple, store it in the result tuple slot and
|
||||
* return it --- unless we find we can project no tuples from
|
||||
* this scan tuple, in which case continue scan.
|
||||
*/
|
||||
resultSlot = ExecProject(scanstate->cstate.cs_ProjInfo, &isDone);
|
||||
if (isDone != ExprEndResult)
|
||||
@@ -144,9 +138,8 @@ ExecScan(Scan *node,
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* Tuple fails qual, so free per-tuple memory and try again.
|
||||
* ----------------
|
||||
/*
|
||||
* Tuple fails qual, so free per-tuple memory and try again.
|
||||
*/
|
||||
ResetExprContext(econtext);
|
||||
}
|
||||
|
@@ -15,7 +15,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/execTuples.c,v 1.47 2001/03/22 03:59:26 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/execTuples.c,v 1.48 2001/03/22 06:16:12 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -134,29 +134,26 @@ ExecCreateTupleTable(int initialSize) /* initial number of slots in
|
||||
TupleTable newtable; /* newly allocated table */
|
||||
TupleTableSlot *array; /* newly allocated slot array */
|
||||
|
||||
/* ----------------
|
||||
* sanity checks
|
||||
* ----------------
|
||||
/*
|
||||
* sanity checks
|
||||
*/
|
||||
Assert(initialSize >= 1);
|
||||
|
||||
/* ----------------
|
||||
* Now allocate our new table along with space for the pointers
|
||||
* to the tuples.
|
||||
/*
|
||||
* Now allocate our new table along with space for the pointers to the
|
||||
* tuples.
|
||||
*/
|
||||
|
||||
newtable = (TupleTable) palloc(sizeof(TupleTableData));
|
||||
array = (TupleTableSlot *) palloc(initialSize * sizeof(TupleTableSlot));
|
||||
|
||||
/* ----------------
|
||||
* clean out the slots we just allocated
|
||||
* ----------------
|
||||
/*
|
||||
* clean out the slots we just allocated
|
||||
*/
|
||||
MemSet(array, 0, initialSize * sizeof(TupleTableSlot));
|
||||
|
||||
/* ----------------
|
||||
* initialize the new table and return it to the caller.
|
||||
* ----------------
|
||||
/*
|
||||
* initialize the new table and return it to the caller.
|
||||
*/
|
||||
newtable->size = initialSize;
|
||||
newtable->next = 0;
|
||||
@@ -182,25 +179,22 @@ ExecDropTupleTable(TupleTable table, /* tuple table */
|
||||
TupleTableSlot *array; /* start of table array */
|
||||
int i; /* counter */
|
||||
|
||||
/* ----------------
|
||||
* sanity checks
|
||||
* ----------------
|
||||
/*
|
||||
* sanity checks
|
||||
*/
|
||||
Assert(table != NULL);
|
||||
|
||||
/* ----------------
|
||||
* get information from the table
|
||||
* ----------------
|
||||
/*
|
||||
* get information from the table
|
||||
*/
|
||||
array = table->array;
|
||||
next = table->next;
|
||||
|
||||
/* ----------------
|
||||
* first free all the valid pointers in the tuple array
|
||||
* and drop refcounts of any referenced buffers,
|
||||
* if that's what the caller wants. (There is probably
|
||||
* no good reason for the caller ever not to want it!)
|
||||
* ----------------
|
||||
/*
|
||||
* first free all the valid pointers in the tuple array and drop
|
||||
* refcounts of any referenced buffers, if that's what the caller
|
||||
* wants. (There is probably no good reason for the caller ever not
|
||||
* to want it!)
|
||||
*/
|
||||
if (shouldFree)
|
||||
{
|
||||
@@ -213,9 +207,8 @@ ExecDropTupleTable(TupleTable table, /* tuple table */
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* finally free the tuple array and the table itself.
|
||||
* ----------------
|
||||
/*
|
||||
* finally free the tuple array and the table itself.
|
||||
*/
|
||||
pfree(array);
|
||||
pfree(table);
|
||||
@@ -242,36 +235,32 @@ ExecAllocTableSlot(TupleTable table)
|
||||
int slotnum; /* new slot number */
|
||||
TupleTableSlot *slot;
|
||||
|
||||
/* ----------------
|
||||
* sanity checks
|
||||
* ----------------
|
||||
/*
|
||||
* sanity checks
|
||||
*/
|
||||
Assert(table != NULL);
|
||||
|
||||
/* ----------------
|
||||
* if our table is full we have to allocate a larger
|
||||
* size table. Since ExecAllocTableSlot() is only called
|
||||
* before the table is ever used to store tuples, we don't
|
||||
* have to worry about the contents of the old table.
|
||||
* If this changes, then we will have to preserve the contents.
|
||||
* -cim 6/23/90
|
||||
/*
|
||||
* if our table is full we have to allocate a larger size table.
|
||||
* Since ExecAllocTableSlot() is only called before the table is ever
|
||||
* used to store tuples, we don't have to worry about the contents of
|
||||
* the old table. If this changes, then we will have to preserve the
|
||||
* contents. -cim 6/23/90
|
||||
*
|
||||
* Unfortunately, we *cannot* do this. All of the nodes in
|
||||
* the plan that have already initialized their slots will have
|
||||
* pointers into _freed_ memory. This leads to bad ends. We
|
||||
* now count the number of slots we will need and create all the
|
||||
* slots we will need ahead of time. The if below should never
|
||||
* happen now. Fail if it does. -mer 4 Aug 1992
|
||||
* ----------------
|
||||
* Unfortunately, we *cannot* do this. All of the nodes in the plan that
|
||||
* have already initialized their slots will have pointers into
|
||||
* _freed_ memory. This leads to bad ends. We now count the number
|
||||
* of slots we will need and create all the slots we will need ahead
|
||||
* of time. The if below should never happen now. Fail if it does.
|
||||
* -mer 4 Aug 1992
|
||||
*/
|
||||
if (table->next >= table->size)
|
||||
elog(ERROR, "Plan requires more slots than are available"
|
||||
"\n\tsend mail to your local executor guru to fix this");
|
||||
|
||||
/* ----------------
|
||||
* at this point, space in the table is guaranteed so we
|
||||
* reserve the next slot, initialize and return it.
|
||||
* ----------------
|
||||
/*
|
||||
* at this point, space in the table is guaranteed so we reserve the
|
||||
* next slot, initialize and return it.
|
||||
*/
|
||||
slotnum = table->next;
|
||||
table->next++;
|
||||
@@ -358,9 +347,9 @@ ExecStoreTuple(HeapTuple tuple,
|
||||
Buffer buffer,
|
||||
bool shouldFree)
|
||||
{
|
||||
/* ----------------
|
||||
* sanity checks
|
||||
* ----------------
|
||||
|
||||
/*
|
||||
* sanity checks
|
||||
*/
|
||||
Assert(slot != NULL);
|
||||
/* passing shouldFree=true for a tuple on a disk page is not sane */
|
||||
@@ -369,10 +358,9 @@ ExecStoreTuple(HeapTuple tuple,
|
||||
/* clear out any old contents of the slot */
|
||||
ExecClearTuple(slot);
|
||||
|
||||
/* ----------------
|
||||
* store the new tuple into the specified slot and
|
||||
* return the slot into which we stored the tuple.
|
||||
* ----------------
|
||||
/*
|
||||
* store the new tuple into the specified slot and return the slot
|
||||
* into which we stored the tuple.
|
||||
*/
|
||||
slot->val = tuple;
|
||||
slot->ttc_buffer = buffer;
|
||||
@@ -401,21 +389,18 @@ ExecClearTuple(TupleTableSlot *slot) /* slot in which to store tuple */
|
||||
{
|
||||
HeapTuple oldtuple; /* prior contents of slot */
|
||||
|
||||
/* ----------------
|
||||
* sanity checks
|
||||
* ----------------
|
||||
/*
|
||||
* sanity checks
|
||||
*/
|
||||
Assert(slot != NULL);
|
||||
|
||||
/* ----------------
|
||||
* get information from the tuple table
|
||||
* ----------------
|
||||
/*
|
||||
* get information from the tuple table
|
||||
*/
|
||||
oldtuple = slot->val;
|
||||
|
||||
/* ----------------
|
||||
* free the old contents of the specified slot if necessary.
|
||||
* ----------------
|
||||
/*
|
||||
* free the old contents of the specified slot if necessary.
|
||||
*/
|
||||
if (slot->ttc_shouldFree && oldtuple != NULL)
|
||||
heap_freetuple(oldtuple);
|
||||
@@ -424,9 +409,8 @@ ExecClearTuple(TupleTableSlot *slot) /* slot in which to store tuple */
|
||||
|
||||
slot->ttc_shouldFree = true;/* probably useless code... */
|
||||
|
||||
/* ----------------
|
||||
* Drop the pin on the referenced buffer, if there is one.
|
||||
* ----------------
|
||||
/*
|
||||
* Drop the pin on the referenced buffer, if there is one.
|
||||
*/
|
||||
if (BufferIsValid(slot->ttc_buffer))
|
||||
ReleaseBuffer(slot->ttc_buffer);
|
||||
@@ -582,24 +566,21 @@ ExecTypeFromTL(List *targetList)
|
||||
Oid restype;
|
||||
int len;
|
||||
|
||||
/* ----------------
|
||||
* examine targetlist - if empty then return NULL
|
||||
* ----------------
|
||||
/*
|
||||
* examine targetlist - if empty then return NULL
|
||||
*/
|
||||
len = ExecTargetListLength(targetList);
|
||||
|
||||
if (len == 0)
|
||||
return NULL;
|
||||
|
||||
/* ----------------
|
||||
* allocate a new typeInfo
|
||||
* ----------------
|
||||
/*
|
||||
* allocate a new typeInfo
|
||||
*/
|
||||
typeInfo = CreateTemplateTupleDesc(len);
|
||||
|
||||
/* ----------------
|
||||
/*
|
||||
* scan list, generate type info for each entry
|
||||
* ----------------
|
||||
*/
|
||||
foreach(tlitem, targetList)
|
||||
{
|
||||
|
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/execUtils.c,v 1.74 2001/03/22 03:59:26 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/execUtils.c,v 1.75 2001/03/22 06:16:12 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -336,18 +336,16 @@ ExecFreeProjectionInfo(CommonState *commonstate)
|
||||
{
|
||||
ProjectionInfo *projInfo;
|
||||
|
||||
/* ----------------
|
||||
* get projection info. if NULL then this node has
|
||||
* none so we just return.
|
||||
* ----------------
|
||||
/*
|
||||
* get projection info. if NULL then this node has none so we just
|
||||
* return.
|
||||
*/
|
||||
projInfo = commonstate->cs_ProjInfo;
|
||||
if (projInfo == NULL)
|
||||
return;
|
||||
|
||||
/* ----------------
|
||||
* clean up memory used.
|
||||
* ----------------
|
||||
/*
|
||||
* clean up memory used.
|
||||
*/
|
||||
if (projInfo->pi_tupValue != NULL)
|
||||
pfree(projInfo->pi_tupValue);
|
||||
@@ -365,18 +363,16 @@ ExecFreeExprContext(CommonState *commonstate)
|
||||
{
|
||||
ExprContext *econtext;
|
||||
|
||||
/* ----------------
|
||||
* get expression context. if NULL then this node has
|
||||
* none so we just return.
|
||||
* ----------------
|
||||
/*
|
||||
* get expression context. if NULL then this node has none so we just
|
||||
* return.
|
||||
*/
|
||||
econtext = commonstate->cs_ExprContext;
|
||||
if (econtext == NULL)
|
||||
return;
|
||||
|
||||
/* ----------------
|
||||
* clean up memory used.
|
||||
* ----------------
|
||||
/*
|
||||
* clean up memory used.
|
||||
*/
|
||||
MemoryContextDelete(econtext->ecxt_per_tuple_memory);
|
||||
pfree(econtext);
|
||||
@@ -476,18 +472,16 @@ ExecOpenIndices(ResultRelInfo *resultRelInfo)
|
||||
IsSystemRelationName(RelationGetRelationName(resultRelation)))
|
||||
return;
|
||||
|
||||
/* ----------------
|
||||
* Get cached list of index OIDs
|
||||
* ----------------
|
||||
/*
|
||||
* Get cached list of index OIDs
|
||||
*/
|
||||
indexoidlist = RelationGetIndexList(resultRelation);
|
||||
len = length(indexoidlist);
|
||||
if (len == 0)
|
||||
return;
|
||||
|
||||
/* ----------------
|
||||
* allocate space for result arrays
|
||||
* ----------------
|
||||
/*
|
||||
* allocate space for result arrays
|
||||
*/
|
||||
relationDescs = (RelationPtr) palloc(len * sizeof(Relation));
|
||||
indexInfoArray = (IndexInfo **) palloc(len * sizeof(IndexInfo *));
|
||||
@@ -496,9 +490,8 @@ ExecOpenIndices(ResultRelInfo *resultRelInfo)
|
||||
resultRelInfo->ri_IndexRelationDescs = relationDescs;
|
||||
resultRelInfo->ri_IndexRelationInfo = indexInfoArray;
|
||||
|
||||
/* ----------------
|
||||
* For each index, open the index relation and save pg_index info.
|
||||
* ----------------
|
||||
/*
|
||||
* For each index, open the index relation and save pg_index info.
|
||||
*/
|
||||
i = 0;
|
||||
foreach(indexoidscan, indexoidlist)
|
||||
@@ -508,24 +501,23 @@ ExecOpenIndices(ResultRelInfo *resultRelInfo)
|
||||
HeapTuple indexTuple;
|
||||
IndexInfo *ii;
|
||||
|
||||
/* ----------------
|
||||
/*
|
||||
* Open (and lock, if necessary) the index relation
|
||||
*
|
||||
* Hack for not btree and hash indices: they use relation level
|
||||
* exclusive locking on update (i.e. - they are not ready for MVCC)
|
||||
* and so we have to exclusively lock indices here to prevent
|
||||
* deadlocks if we will scan them - index_beginscan places
|
||||
* exclusive locking on update (i.e. - they are not ready for
|
||||
* MVCC) and so we have to exclusively lock indices here to
|
||||
* prevent deadlocks if we will scan them - index_beginscan places
|
||||
* AccessShareLock, indices update methods don't use locks at all.
|
||||
* We release this lock in ExecCloseIndices. Note, that hashes use
|
||||
* page level locking - i.e. are not deadlock-free - let's them be
|
||||
* on their way -:)) vadim 03-12-1998
|
||||
*
|
||||
* If there are multiple not-btree-or-hash indices, all backends must
|
||||
* lock the indices in the same order or we will get deadlocks here
|
||||
* during concurrent updates. This is now guaranteed by
|
||||
* lock the indices in the same order or we will get deadlocks
|
||||
* here during concurrent updates. This is now guaranteed by
|
||||
* RelationGetIndexList(), which promises to return the index list
|
||||
* in OID order. tgl 06-19-2000
|
||||
* ----------------
|
||||
*/
|
||||
indexDesc = index_open(indexOid);
|
||||
|
||||
@@ -533,9 +525,8 @@ ExecOpenIndices(ResultRelInfo *resultRelInfo)
|
||||
indexDesc->rd_rel->relam != HASH_AM_OID)
|
||||
LockRelation(indexDesc, AccessExclusiveLock);
|
||||
|
||||
/* ----------------
|
||||
* Get the pg_index tuple for the index
|
||||
* ----------------
|
||||
/*
|
||||
* Get the pg_index tuple for the index
|
||||
*/
|
||||
indexTuple = SearchSysCache(INDEXRELID,
|
||||
ObjectIdGetDatum(indexOid),
|
||||
@@ -543,9 +534,8 @@ ExecOpenIndices(ResultRelInfo *resultRelInfo)
|
||||
if (!HeapTupleIsValid(indexTuple))
|
||||
elog(ERROR, "ExecOpenIndices: index %u not found", indexOid);
|
||||
|
||||
/* ----------------
|
||||
* extract the index key information from the tuple
|
||||
* ----------------
|
||||
/*
|
||||
* extract the index key information from the tuple
|
||||
*/
|
||||
ii = BuildIndexInfo(indexTuple);
|
||||
|
||||
@@ -647,9 +637,8 @@ ExecInsertIndexTuples(TupleTableSlot *slot,
|
||||
/* Arrange for econtext's scan tuple to be the tuple under test */
|
||||
econtext->ecxt_scantuple = slot;
|
||||
|
||||
/* ----------------
|
||||
* for each index, form and insert the index tuple
|
||||
* ----------------
|
||||
/*
|
||||
* for each index, form and insert the index tuple
|
||||
*/
|
||||
for (i = 0; i < numIndices; i++)
|
||||
{
|
||||
@@ -669,10 +658,9 @@ ExecInsertIndexTuples(TupleTableSlot *slot,
|
||||
continue;
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* FormIndexDatum fills in its datum and null parameters
|
||||
* with attribute information taken from the given heap tuple.
|
||||
* ----------------
|
||||
/*
|
||||
* FormIndexDatum fills in its datum and null parameters with
|
||||
* attribute information taken from the given heap tuple.
|
||||
*/
|
||||
FormIndexDatum(indexInfo,
|
||||
heapTuple,
|
||||
@@ -687,9 +675,8 @@ ExecInsertIndexTuples(TupleTableSlot *slot,
|
||||
&(heapTuple->t_self), /* tid of heap tuple */
|
||||
heapRelation);
|
||||
|
||||
/* ----------------
|
||||
* keep track of index inserts for debugging
|
||||
* ----------------
|
||||
/*
|
||||
* keep track of index inserts for debugging
|
||||
*/
|
||||
IncrIndexInserted();
|
||||
|
||||
|
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/functions.c,v 1.44 2001/03/22 03:59:26 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/functions.c,v 1.45 2001/03/22 06:16:12 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -162,9 +162,8 @@ init_sql_fcache(FmgrInfo *finfo)
|
||||
Datum tmp;
|
||||
bool isNull;
|
||||
|
||||
/* ----------------
|
||||
* get the procedure tuple corresponding to the given function Oid
|
||||
* ----------------
|
||||
/*
|
||||
* get the procedure tuple corresponding to the given function Oid
|
||||
*/
|
||||
procedureTuple = SearchSysCache(PROCOID,
|
||||
ObjectIdGetDatum(foid),
|
||||
@@ -175,9 +174,8 @@ init_sql_fcache(FmgrInfo *finfo)
|
||||
|
||||
procedureStruct = (Form_pg_proc) GETSTRUCT(procedureTuple);
|
||||
|
||||
/* ----------------
|
||||
* get the return type from the procedure tuple
|
||||
* ----------------
|
||||
/*
|
||||
* get the return type from the procedure tuple
|
||||
*/
|
||||
typeTuple = SearchSysCache(TYPEOID,
|
||||
ObjectIdGetDatum(procedureStruct->prorettype),
|
||||
@@ -191,9 +189,8 @@ init_sql_fcache(FmgrInfo *finfo)
|
||||
fcache = (SQLFunctionCachePtr) palloc(sizeof(SQLFunctionCache));
|
||||
MemSet(fcache, 0, sizeof(SQLFunctionCache));
|
||||
|
||||
/* ----------------
|
||||
* get the type length and by-value flag from the type tuple
|
||||
* ----------------
|
||||
/*
|
||||
* get the type length and by-value flag from the type tuple
|
||||
*/
|
||||
fcache->typlen = typeStruct->typlen;
|
||||
if (typeStruct->typrelid == InvalidOid)
|
||||
|
@@ -46,7 +46,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/nodeAgg.c,v 1.76 2001/03/22 03:59:27 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/nodeAgg.c,v 1.77 2001/03/22 06:16:12 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -202,13 +202,12 @@ initialize_aggregate(AggStatePerAgg peraggstate)
|
||||
peraggstate->transValue = peraggstate->initValue;
|
||||
peraggstate->transValueIsNull = peraggstate->initValueIsNull;
|
||||
|
||||
/* ------------------------------------------
|
||||
/*
|
||||
* If the initial value for the transition state doesn't exist in the
|
||||
* pg_aggregate table then we will let the first non-NULL value returned
|
||||
* from the outer procNode become the initial value. (This is useful for
|
||||
* aggregates like max() and min().) The noTransValue flag signals that
|
||||
* we still need to do this.
|
||||
* ------------------------------------------
|
||||
* pg_aggregate table then we will let the first non-NULL value
|
||||
* returned from the outer procNode become the initial value. (This is
|
||||
* useful for aggregates like max() and min().) The noTransValue flag
|
||||
* signals that we still need to do this.
|
||||
*/
|
||||
peraggstate->noTransValue = peraggstate->initValueIsNull;
|
||||
}
|
||||
@@ -477,9 +476,8 @@ ExecAgg(Agg *node)
|
||||
int aggno;
|
||||
bool isNull;
|
||||
|
||||
/* ---------------------
|
||||
* get state info from node
|
||||
* ---------------------
|
||||
/*
|
||||
* get state info from node
|
||||
*/
|
||||
aggstate = node->aggstate;
|
||||
estate = node->plan.state;
|
||||
@@ -516,9 +514,8 @@ ExecAgg(Agg *node)
|
||||
|
||||
inputTuple = NULL; /* no saved input tuple yet */
|
||||
|
||||
/* ----------------
|
||||
* for each tuple from the outer plan, update all the aggregates
|
||||
* ----------------
|
||||
/*
|
||||
* for each tuple from the outer plan, update all the aggregates
|
||||
*/
|
||||
for (;;)
|
||||
{
|
||||
@@ -829,9 +826,8 @@ ExecInitAgg(Agg *node, EState *estate, Plan *parent)
|
||||
outerPlan = outerPlan(node);
|
||||
ExecInitNode(outerPlan, estate, (Plan *) node);
|
||||
|
||||
/* ----------------
|
||||
* initialize source tuple type.
|
||||
* ----------------
|
||||
/*
|
||||
* initialize source tuple type.
|
||||
*/
|
||||
ExecAssignScanTypeFromOuterPlan((Plan *) node, &aggstate->csstate);
|
||||
|
||||
|
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/nodeAppend.c,v 1.39 2001/01/24 19:42:54 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/nodeAppend.c,v 1.40 2001/03/22 06:16:12 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -81,9 +81,8 @@ exec_append_initialize_next(Append *node)
|
||||
int whichplan;
|
||||
int nplans;
|
||||
|
||||
/* ----------------
|
||||
* get information from the append node
|
||||
* ----------------
|
||||
/*
|
||||
* get information from the append node
|
||||
*/
|
||||
estate = node->plan.state;
|
||||
appendstate = node->appendstate;
|
||||
@@ -92,35 +91,34 @@ exec_append_initialize_next(Append *node)
|
||||
|
||||
if (whichplan < 0)
|
||||
{
|
||||
/* ----------------
|
||||
* if scanning in reverse, we start at
|
||||
* the last scan in the list and then
|
||||
* proceed back to the first.. in any case
|
||||
* we inform ExecProcAppend that we are
|
||||
* at the end of the line by returning FALSE
|
||||
* ----------------
|
||||
|
||||
/*
|
||||
* if scanning in reverse, we start at the last scan in the list
|
||||
* and then proceed back to the first.. in any case we inform
|
||||
* ExecProcAppend that we are at the end of the line by returning
|
||||
* FALSE
|
||||
*/
|
||||
appendstate->as_whichplan = 0;
|
||||
return FALSE;
|
||||
}
|
||||
else if (whichplan >= nplans)
|
||||
{
|
||||
/* ----------------
|
||||
* as above, end the scan if we go beyond
|
||||
* the last scan in our list..
|
||||
* ----------------
|
||||
|
||||
/*
|
||||
* as above, end the scan if we go beyond the last scan in our
|
||||
* list..
|
||||
*/
|
||||
appendstate->as_whichplan = nplans - 1;
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* ----------------
|
||||
* initialize the scan
|
||||
|
||||
/*
|
||||
* initialize the scan
|
||||
*
|
||||
* If we are controlling the target relation, select the proper
|
||||
* active ResultRelInfo and junk filter for this target.
|
||||
* ----------------
|
||||
*/
|
||||
if (node->isTarget)
|
||||
{
|
||||
@@ -162,10 +160,8 @@ ExecInitAppend(Append *node, EState *estate, Plan *parent)
|
||||
|
||||
CXT1_printf("ExecInitAppend: context is %d\n", CurrentMemoryContext);
|
||||
|
||||
/* ----------------
|
||||
* assign execution state to node and get information
|
||||
* for append state
|
||||
* ----------------
|
||||
/*
|
||||
* assign execution state to node and get information for append state
|
||||
*/
|
||||
node->plan.state = estate;
|
||||
|
||||
@@ -175,9 +171,8 @@ ExecInitAppend(Append *node, EState *estate, Plan *parent)
|
||||
initialized = (bool *) palloc(nplans * sizeof(bool));
|
||||
MemSet(initialized, 0, nplans * sizeof(bool));
|
||||
|
||||
/* ----------------
|
||||
* create new AppendState for our append node
|
||||
* ----------------
|
||||
/*
|
||||
* create new AppendState for our append node
|
||||
*/
|
||||
appendstate = makeNode(AppendState);
|
||||
appendstate->as_whichplan = 0;
|
||||
@@ -186,26 +181,24 @@ ExecInitAppend(Append *node, EState *estate, Plan *parent)
|
||||
|
||||
node->appendstate = appendstate;
|
||||
|
||||
/* ----------------
|
||||
* Miscellaneous initialization
|
||||
/*
|
||||
* Miscellaneous initialization
|
||||
*
|
||||
* Append plans don't have expression contexts because they
|
||||
* never call ExecQual or ExecProject.
|
||||
* ----------------
|
||||
* Append plans don't have expression contexts because they never call
|
||||
* ExecQual or ExecProject.
|
||||
*/
|
||||
|
||||
#define APPEND_NSLOTS 1
|
||||
/* ----------------
|
||||
* append nodes still have Result slots, which hold pointers
|
||||
* to tuples, so we have to initialize them.
|
||||
* ----------------
|
||||
|
||||
/*
|
||||
* append nodes still have Result slots, which hold pointers to
|
||||
* tuples, so we have to initialize them.
|
||||
*/
|
||||
ExecInitResultTupleSlot(estate, &appendstate->cstate);
|
||||
|
||||
/* ----------------
|
||||
* call ExecInitNode on each of the plans in our list
|
||||
* and save the results into the array "initialized"
|
||||
* ----------------
|
||||
/*
|
||||
* call ExecInitNode on each of the plans in our list and save the
|
||||
* results into the array "initialized"
|
||||
*/
|
||||
for (i = 0; i < nplans; i++)
|
||||
{
|
||||
@@ -216,16 +209,14 @@ ExecInitAppend(Append *node, EState *estate, Plan *parent)
|
||||
initialized[i] = ExecInitNode(initNode, estate, (Plan *) node);
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* initialize tuple type
|
||||
* ----------------
|
||||
/*
|
||||
* initialize tuple type
|
||||
*/
|
||||
ExecAssignResultTypeFromTL((Plan *) node, &appendstate->cstate);
|
||||
appendstate->cstate.cs_ProjInfo = NULL;
|
||||
|
||||
/* ----------------
|
||||
* return the result from the first subplan's initialization
|
||||
* ----------------
|
||||
/*
|
||||
* return the result from the first subplan's initialization
|
||||
*/
|
||||
appendstate->as_whichplan = 0;
|
||||
exec_append_initialize_next(node);
|
||||
@@ -264,9 +255,8 @@ ExecProcAppend(Append *node)
|
||||
TupleTableSlot *result_slot;
|
||||
ScanDirection direction;
|
||||
|
||||
/* ----------------
|
||||
* get information from the node
|
||||
* ----------------
|
||||
/*
|
||||
* get information from the node
|
||||
*/
|
||||
appendstate = node->appendstate;
|
||||
estate = node->plan.state;
|
||||
@@ -275,49 +265,46 @@ ExecProcAppend(Append *node)
|
||||
whichplan = appendstate->as_whichplan;
|
||||
result_slot = appendstate->cstate.cs_ResultTupleSlot;
|
||||
|
||||
/* ----------------
|
||||
* figure out which subplan we are currently processing
|
||||
* ----------------
|
||||
/*
|
||||
* figure out which subplan we are currently processing
|
||||
*/
|
||||
subnode = (Plan *) nth(whichplan, appendplans);
|
||||
|
||||
if (subnode == NULL)
|
||||
elog(DEBUG, "ExecProcAppend: subnode is NULL");
|
||||
|
||||
/* ----------------
|
||||
* get a tuple from the subplan
|
||||
* ----------------
|
||||
/*
|
||||
* get a tuple from the subplan
|
||||
*/
|
||||
result = ExecProcNode(subnode, (Plan *) node);
|
||||
|
||||
if (!TupIsNull(result))
|
||||
{
|
||||
/* ----------------
|
||||
* if the subplan gave us something then place a copy of
|
||||
* whatever we get into our result slot and return it.
|
||||
|
||||
/*
|
||||
* if the subplan gave us something then place a copy of whatever
|
||||
* we get into our result slot and return it.
|
||||
*
|
||||
* Note we rely on the subplan to retain ownership of the
|
||||
* tuple for as long as we need it --- we don't copy it.
|
||||
* ----------------
|
||||
* Note we rely on the subplan to retain ownership of the tuple for
|
||||
* as long as we need it --- we don't copy it.
|
||||
*/
|
||||
return ExecStoreTuple(result->val, result_slot, InvalidBuffer, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* ----------------
|
||||
* .. go on to the "next" subplan in the appropriate
|
||||
* direction and try processing again (recursively)
|
||||
* ----------------
|
||||
|
||||
/*
|
||||
* .. go on to the "next" subplan in the appropriate direction and
|
||||
* try processing again (recursively)
|
||||
*/
|
||||
if (ScanDirectionIsForward(direction))
|
||||
appendstate->as_whichplan++;
|
||||
else
|
||||
appendstate->as_whichplan--;
|
||||
|
||||
/* ----------------
|
||||
* return something from next node or an empty slot
|
||||
* if all of our subplans have been exhausted.
|
||||
* ----------------
|
||||
/*
|
||||
* return something from next node or an empty slot if all of our
|
||||
* subplans have been exhausted.
|
||||
*/
|
||||
if (exec_append_initialize_next(node))
|
||||
{
|
||||
@@ -347,9 +334,8 @@ ExecEndAppend(Append *node)
|
||||
bool *initialized;
|
||||
int i;
|
||||
|
||||
/* ----------------
|
||||
* get information from the node
|
||||
* ----------------
|
||||
/*
|
||||
* get information from the node
|
||||
*/
|
||||
appendstate = node->appendstate;
|
||||
estate = node->plan.state;
|
||||
@@ -357,9 +343,8 @@ ExecEndAppend(Append *node)
|
||||
nplans = appendstate->as_nplans;
|
||||
initialized = appendstate->as_initialized;
|
||||
|
||||
/* ----------------
|
||||
* shut down each of the subscans
|
||||
* ----------------
|
||||
/*
|
||||
* shut down each of the subscans
|
||||
*/
|
||||
for (i = 0; i < nplans; i++)
|
||||
{
|
||||
|
@@ -15,7 +15,7 @@
|
||||
* locate group boundaries.
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/nodeGroup.c,v 1.42 2001/03/22 03:59:27 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/nodeGroup.c,v 1.43 2001/03/22 06:16:12 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -76,9 +76,8 @@ ExecGroupEveryTuple(Group *node)
|
||||
ProjectionInfo *projInfo;
|
||||
TupleTableSlot *resultSlot;
|
||||
|
||||
/* ---------------------
|
||||
* get state info from node
|
||||
* ---------------------
|
||||
/*
|
||||
* get state info from node
|
||||
*/
|
||||
grpstate = node->grpstate;
|
||||
if (grpstate->grp_done)
|
||||
@@ -156,10 +155,9 @@ ExecGroupEveryTuple(Group *node)
|
||||
InvalidBuffer, false);
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* form a projection tuple, store it in the result tuple
|
||||
* slot and return it.
|
||||
* ----------------
|
||||
/*
|
||||
* form a projection tuple, store it in the result tuple slot and
|
||||
* return it.
|
||||
*/
|
||||
projInfo = grpstate->csstate.cstate.cs_ProjInfo;
|
||||
|
||||
@@ -187,9 +185,8 @@ ExecGroupOneTuple(Group *node)
|
||||
ProjectionInfo *projInfo;
|
||||
TupleTableSlot *resultSlot;
|
||||
|
||||
/* ---------------------
|
||||
* get state info from node
|
||||
* ---------------------
|
||||
/*
|
||||
* get state info from node
|
||||
*/
|
||||
grpstate = node->grpstate;
|
||||
if (grpstate->grp_done)
|
||||
@@ -243,10 +240,9 @@ ExecGroupOneTuple(Group *node)
|
||||
break;
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* form a projection tuple, store it in the result tuple
|
||||
* slot and return it.
|
||||
* ----------------
|
||||
/*
|
||||
* form a projection tuple, store it in the result tuple slot and
|
||||
* return it.
|
||||
*/
|
||||
projInfo = grpstate->csstate.cstate.cs_ProjInfo;
|
||||
|
||||
@@ -316,9 +312,8 @@ ExecInitGroup(Group *node, EState *estate, Plan *parent)
|
||||
outerPlan = outerPlan(node);
|
||||
ExecInitNode(outerPlan, estate, (Plan *) node);
|
||||
|
||||
/* ----------------
|
||||
* initialize tuple type.
|
||||
* ----------------
|
||||
/*
|
||||
* initialize tuple type.
|
||||
*/
|
||||
ExecAssignScanTypeFromOuterPlan((Plan *) node, &grpstate->csstate);
|
||||
|
||||
|
@@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
*
|
||||
* $Id: nodeHash.c,v 1.55 2001/03/22 03:59:27 momjian Exp $
|
||||
* $Id: nodeHash.c,v 1.56 2001/03/22 06:16:12 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -55,9 +55,8 @@ ExecHash(Hash *node)
|
||||
int nbatch;
|
||||
int i;
|
||||
|
||||
/* ----------------
|
||||
* get state info from node
|
||||
* ----------------
|
||||
/*
|
||||
* get state info from node
|
||||
*/
|
||||
|
||||
hashstate = node->hashstate;
|
||||
@@ -72,25 +71,23 @@ ExecHash(Hash *node)
|
||||
|
||||
if (nbatch > 0)
|
||||
{
|
||||
/* ----------------
|
||||
* Open temp files for inner batches, if needed.
|
||||
* Note that file buffers are palloc'd in regular executor context.
|
||||
* ----------------
|
||||
|
||||
/*
|
||||
* Open temp files for inner batches, if needed. Note that file
|
||||
* buffers are palloc'd in regular executor context.
|
||||
*/
|
||||
for (i = 0; i < nbatch; i++)
|
||||
hashtable->innerBatchFile[i] = BufFileCreateTemp();
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* set expression context
|
||||
* ----------------
|
||||
/*
|
||||
* set expression context
|
||||
*/
|
||||
hashkey = node->hashkey;
|
||||
econtext = hashstate->cstate.cs_ExprContext;
|
||||
|
||||
/* ----------------
|
||||
* get all inner tuples and insert into the hash table (or temp files)
|
||||
* ----------------
|
||||
/*
|
||||
* get all inner tuples and insert into the hash table (or temp files)
|
||||
*/
|
||||
for (;;)
|
||||
{
|
||||
@@ -102,10 +99,9 @@ ExecHash(Hash *node)
|
||||
ExecClearTuple(slot);
|
||||
}
|
||||
|
||||
/* ---------------------
|
||||
* Return the slot so that we have the tuple descriptor
|
||||
* when we need to save/restore them. -Jeff 11 July 1991
|
||||
* ---------------------
|
||||
/*
|
||||
* Return the slot so that we have the tuple descriptor when we need
|
||||
* to save/restore them. -Jeff 11 July 1991
|
||||
*/
|
||||
return slot;
|
||||
}
|
||||
@@ -125,45 +121,39 @@ ExecInitHash(Hash *node, EState *estate, Plan *parent)
|
||||
SO1_printf("ExecInitHash: %s\n",
|
||||
"initializing hash node");
|
||||
|
||||
/* ----------------
|
||||
* assign the node's execution state
|
||||
* ----------------
|
||||
/*
|
||||
* assign the node's execution state
|
||||
*/
|
||||
node->plan.state = estate;
|
||||
|
||||
/* ----------------
|
||||
/*
|
||||
* create state structure
|
||||
* ----------------
|
||||
*/
|
||||
hashstate = makeNode(HashState);
|
||||
node->hashstate = hashstate;
|
||||
hashstate->hashtable = NULL;
|
||||
|
||||
/* ----------------
|
||||
* Miscellaneous initialization
|
||||
/*
|
||||
* Miscellaneous initialization
|
||||
*
|
||||
* + create expression context for node
|
||||
* ----------------
|
||||
* create expression context for node
|
||||
*/
|
||||
ExecAssignExprContext(estate, &hashstate->cstate);
|
||||
|
||||
/* ----------------
|
||||
/*
|
||||
* initialize our result slot
|
||||
* ----------------
|
||||
*/
|
||||
ExecInitResultTupleSlot(estate, &hashstate->cstate);
|
||||
|
||||
/* ----------------
|
||||
/*
|
||||
* initializes child nodes
|
||||
* ----------------
|
||||
*/
|
||||
outerPlan = outerPlan(node);
|
||||
ExecInitNode(outerPlan, estate, (Plan *) node);
|
||||
|
||||
/* ----------------
|
||||
* initialize tuple type. no need to initialize projection
|
||||
* info because this node doesn't do projections
|
||||
* ----------------
|
||||
/*
|
||||
* initialize tuple type. no need to initialize projection info
|
||||
* because this node doesn't do projections
|
||||
*/
|
||||
ExecAssignResultTypeFromOuterPlan((Plan *) node, &hashstate->cstate);
|
||||
hashstate->cstate.cs_ProjInfo = NULL;
|
||||
@@ -192,23 +182,20 @@ ExecEndHash(Hash *node)
|
||||
HashState *hashstate;
|
||||
Plan *outerPlan;
|
||||
|
||||
/* ----------------
|
||||
* get info from the hash state
|
||||
* ----------------
|
||||
/*
|
||||
* get info from the hash state
|
||||
*/
|
||||
hashstate = node->hashstate;
|
||||
|
||||
/* ----------------
|
||||
* free projection info. no need to free result type info
|
||||
* because that came from the outer plan...
|
||||
* ----------------
|
||||
/*
|
||||
* free projection info. no need to free result type info because
|
||||
* that came from the outer plan...
|
||||
*/
|
||||
ExecFreeProjectionInfo(&hashstate->cstate);
|
||||
ExecFreeExprContext(&hashstate->cstate);
|
||||
|
||||
/* ----------------
|
||||
* shut down the subplan
|
||||
* ----------------
|
||||
/*
|
||||
* shut down the subplan
|
||||
*/
|
||||
outerPlan = outerPlan(node);
|
||||
ExecEndNode(outerPlan, (Plan *) node);
|
||||
@@ -239,13 +226,13 @@ ExecHashTableCreate(Hash *node)
|
||||
int i;
|
||||
MemoryContext oldcxt;
|
||||
|
||||
/* ----------------
|
||||
* Get information about the size of the relation to be hashed
|
||||
* (it's the "outer" subtree of this node, but the inner relation of
|
||||
* the hashjoin).
|
||||
* Caution: this is only the planner's estimates, and so
|
||||
* can't be trusted too far. Apply a healthy fudge factor.
|
||||
* ----------------
|
||||
/*
|
||||
* Get information about the size of the relation to be hashed (it's
|
||||
* the "outer" subtree of this node, but the inner relation of the
|
||||
* hashjoin).
|
||||
*
|
||||
* Caution: this is only the planner's estimates, and so can't be trusted
|
||||
* too far. Apply a healthy fudge factor.
|
||||
*/
|
||||
outerNode = outerPlan(node);
|
||||
ntuples = outerNode->plan_rows;
|
||||
@@ -331,11 +318,11 @@ ExecHashTableCreate(Hash *node)
|
||||
nbatch, totalbuckets, nbuckets);
|
||||
#endif
|
||||
|
||||
/* ----------------
|
||||
* Initialize the hash table control block.
|
||||
* The hashtable control block is just palloc'd from the executor's
|
||||
* per-query memory context.
|
||||
* ----------------
|
||||
/*
|
||||
* Initialize the hash table control block.
|
||||
*
|
||||
* The hashtable control block is just palloc'd from the executor's
|
||||
* per-query memory context.
|
||||
*/
|
||||
hashtable = (HashJoinTable) palloc(sizeof(HashTableData));
|
||||
hashtable->nbuckets = nbuckets;
|
||||
@@ -348,18 +335,16 @@ ExecHashTableCreate(Hash *node)
|
||||
hashtable->innerBatchSize = NULL;
|
||||
hashtable->outerBatchSize = NULL;
|
||||
|
||||
/* ----------------
|
||||
* Get info about the datatype of the hash key.
|
||||
* ----------------
|
||||
/*
|
||||
* Get info about the datatype of the hash key.
|
||||
*/
|
||||
get_typlenbyval(exprType(node->hashkey),
|
||||
&hashtable->typLen,
|
||||
&hashtable->typByVal);
|
||||
|
||||
/* ----------------
|
||||
* Create temporary memory contexts in which to keep the hashtable
|
||||
* working storage. See notes in executor/hashjoin.h.
|
||||
* ----------------
|
||||
/*
|
||||
* Create temporary memory contexts in which to keep the hashtable
|
||||
* working storage. See notes in executor/hashjoin.h.
|
||||
*/
|
||||
hashtable->hashCxt = AllocSetContextCreate(CurrentMemoryContext,
|
||||
"HashTableContext",
|
||||
@@ -379,9 +364,9 @@ ExecHashTableCreate(Hash *node)
|
||||
|
||||
if (nbatch > 0)
|
||||
{
|
||||
/* ---------------
|
||||
* allocate and initialize the file arrays in hashCxt
|
||||
* ---------------
|
||||
|
||||
/*
|
||||
* allocate and initialize the file arrays in hashCxt
|
||||
*/
|
||||
hashtable->innerBatchFile = (BufFile **)
|
||||
palloc(nbatch * sizeof(BufFile *));
|
||||
@@ -464,15 +449,14 @@ ExecHashTableInsert(HashJoinTable hashtable,
|
||||
TupleTableSlot *slot = econtext->ecxt_innertuple;
|
||||
HeapTuple heapTuple = slot->val;
|
||||
|
||||
/* ----------------
|
||||
* decide whether to put the tuple in the hash table or a tmp file
|
||||
* ----------------
|
||||
/*
|
||||
* decide whether to put the tuple in the hash table or a tmp file
|
||||
*/
|
||||
if (bucketno < hashtable->nbuckets)
|
||||
{
|
||||
/* ---------------
|
||||
* put the tuple in hash table
|
||||
* ---------------
|
||||
|
||||
/*
|
||||
* put the tuple in hash table
|
||||
*/
|
||||
HashJoinTuple hashTuple;
|
||||
int hashTupleSize;
|
||||
@@ -496,9 +480,9 @@ ExecHashTableInsert(HashJoinTable hashtable,
|
||||
}
|
||||
else
|
||||
{
|
||||
/* -----------------
|
||||
|
||||
/*
|
||||
* put the tuple into a tmp file for other batches
|
||||
* -----------------
|
||||
*/
|
||||
int batchno = (hashtable->nbatch * (bucketno - hashtable->nbuckets)) /
|
||||
(hashtable->totalbuckets - hashtable->nbuckets);
|
||||
@@ -524,20 +508,18 @@ ExecHashGetBucket(HashJoinTable hashtable,
|
||||
Datum keyval;
|
||||
bool isNull;
|
||||
|
||||
/* ----------------
|
||||
* Get the join attribute value of the tuple
|
||||
/*
|
||||
* Get the join attribute value of the tuple
|
||||
*
|
||||
* We reset the eval context each time to avoid any possibility
|
||||
* of memory leaks in the hash function.
|
||||
* ----------------
|
||||
* We reset the eval context each time to avoid any possibility of memory
|
||||
* leaks in the hash function.
|
||||
*/
|
||||
ResetExprContext(econtext);
|
||||
|
||||
keyval = ExecEvalExprSwitchContext(hashkey, econtext, &isNull, NULL);
|
||||
|
||||
/* ------------------
|
||||
* compute the hash function
|
||||
* ------------------
|
||||
/*
|
||||
* compute the hash function
|
||||
*/
|
||||
if (isNull)
|
||||
bucketno = 0;
|
||||
@@ -606,9 +588,8 @@ ExecScanHashBucket(HashJoinState *hjstate,
|
||||
hashTuple = hashTuple->next;
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* no match
|
||||
* ----------------
|
||||
/*
|
||||
* no match
|
||||
*/
|
||||
return NULL;
|
||||
}
|
||||
|
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/nodeHashjoin.c,v 1.37 2001/03/22 03:59:27 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/nodeHashjoin.c,v 1.38 2001/03/22 06:16:13 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -64,9 +64,8 @@ ExecHashJoin(HashJoin *node)
|
||||
int i;
|
||||
bool hashPhaseDone;
|
||||
|
||||
/* ----------------
|
||||
* get information from HashJoin node
|
||||
* ----------------
|
||||
/*
|
||||
* get information from HashJoin node
|
||||
*/
|
||||
hjstate = node->hashjoinstate;
|
||||
hjclauses = node->hashclauses;
|
||||
@@ -79,18 +78,16 @@ ExecHashJoin(HashJoin *node)
|
||||
hashPhaseDone = hjstate->hj_hashdone;
|
||||
dir = estate->es_direction;
|
||||
|
||||
/* -----------------
|
||||
/*
|
||||
* get information from HashJoin state
|
||||
* -----------------
|
||||
*/
|
||||
hashtable = hjstate->hj_HashTable;
|
||||
econtext = hjstate->jstate.cs_ExprContext;
|
||||
|
||||
/* ----------------
|
||||
* Check to see if we're still projecting out tuples from a previous
|
||||
* join tuple (because there is a function-returning-set in the
|
||||
* projection expressions). If so, try to project another one.
|
||||
* ----------------
|
||||
/*
|
||||
* Check to see if we're still projecting out tuples from a previous
|
||||
* join tuple (because there is a function-returning-set in the
|
||||
* projection expressions). If so, try to project another one.
|
||||
*/
|
||||
if (hjstate->jstate.cs_TupFromTlist)
|
||||
{
|
||||
@@ -103,42 +100,39 @@ ExecHashJoin(HashJoin *node)
|
||||
hjstate->jstate.cs_TupFromTlist = false;
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* Reset per-tuple memory context to free any expression evaluation
|
||||
* storage allocated in the previous tuple cycle. Note this can't
|
||||
* happen until we're done projecting out tuples from a join tuple.
|
||||
* ----------------
|
||||
/*
|
||||
* Reset per-tuple memory context to free any expression evaluation
|
||||
* storage allocated in the previous tuple cycle. Note this can't
|
||||
* happen until we're done projecting out tuples from a join tuple.
|
||||
*/
|
||||
ResetExprContext(econtext);
|
||||
|
||||
/* ----------------
|
||||
* if this is the first call, build the hash table for inner relation
|
||||
* ----------------
|
||||
/*
|
||||
* if this is the first call, build the hash table for inner relation
|
||||
*/
|
||||
if (!hashPhaseDone)
|
||||
{ /* if the hash phase not completed */
|
||||
if (hashtable == NULL)
|
||||
{ /* if the hash table has not been created */
|
||||
/* ----------------
|
||||
|
||||
/*
|
||||
* create the hash table
|
||||
* ----------------
|
||||
*/
|
||||
hashtable = ExecHashTableCreate(hashNode);
|
||||
hjstate->hj_HashTable = hashtable;
|
||||
hjstate->hj_InnerHashKey = hashNode->hashkey;
|
||||
|
||||
/* ----------------
|
||||
/*
|
||||
* execute the Hash node, to build the hash table
|
||||
* ----------------
|
||||
*/
|
||||
hashNode->hashstate->hashtable = hashtable;
|
||||
innerTupleSlot = ExecProcNode((Plan *) hashNode, (Plan *) node);
|
||||
}
|
||||
hjstate->hj_hashdone = true;
|
||||
/* ----------------
|
||||
* Open temp files for outer batches, if needed.
|
||||
* Note that file buffers are palloc'd in regular executor context.
|
||||
* ----------------
|
||||
|
||||
/*
|
||||
* Open temp files for outer batches, if needed. Note that file
|
||||
* buffers are palloc'd in regular executor context.
|
||||
*/
|
||||
for (i = 0; i < hashtable->nbatch; i++)
|
||||
hashtable->outerBatchFile[i] = BufFileCreateTemp();
|
||||
@@ -146,9 +140,8 @@ ExecHashJoin(HashJoin *node)
|
||||
else if (hashtable == NULL)
|
||||
return NULL;
|
||||
|
||||
/* ----------------
|
||||
* Now get an outer tuple and probe into the hash table for matches
|
||||
* ----------------
|
||||
/*
|
||||
* Now get an outer tuple and probe into the hash table for matches
|
||||
*/
|
||||
outerTupleSlot = hjstate->jstate.cs_OuterTupleSlot;
|
||||
outerVar = (Node *) get_leftop(clause);
|
||||
@@ -188,11 +181,10 @@ ExecHashJoin(HashJoin *node)
|
||||
outerVar);
|
||||
hjstate->hj_CurTuple = NULL;
|
||||
|
||||
/* ----------------
|
||||
* Now we've got an outer tuple and the corresponding hash bucket,
|
||||
* but this tuple may not belong to the current batch.
|
||||
* This need only be checked in the first pass.
|
||||
* ----------------
|
||||
/*
|
||||
* Now we've got an outer tuple and the corresponding hash
|
||||
* bucket, but this tuple may not belong to the current batch.
|
||||
* This need only be checked in the first pass.
|
||||
*/
|
||||
if (hashtable->curbatch == 0)
|
||||
{
|
||||
@@ -240,14 +232,13 @@ ExecHashJoin(HashJoin *node)
|
||||
/* reset temp memory each time to avoid leaks from qual expr */
|
||||
ResetExprContext(econtext);
|
||||
|
||||
/* ----------------
|
||||
* if we pass the qual, then save state for next call and
|
||||
* have ExecProject form the projection, store it
|
||||
* in the tuple table, and return the slot.
|
||||
/*
|
||||
* if we pass the qual, then save state for next call and have
|
||||
* ExecProject form the projection, store it in the tuple
|
||||
* table, and return the slot.
|
||||
*
|
||||
* Only the joinquals determine MatchedOuter status,
|
||||
* but all quals must pass to actually return the tuple.
|
||||
* ----------------
|
||||
* Only the joinquals determine MatchedOuter status, but all
|
||||
* quals must pass to actually return the tuple.
|
||||
*/
|
||||
if (ExecQual(joinqual, econtext, false))
|
||||
{
|
||||
@@ -269,11 +260,10 @@ ExecHashJoin(HashJoin *node)
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* Now the current outer tuple has run out of matches,
|
||||
* so check whether to emit a dummy outer-join tuple.
|
||||
* If not, loop around to get a new outer tuple.
|
||||
* ----------------
|
||||
/*
|
||||
* Now the current outer tuple has run out of matches, so check
|
||||
* whether to emit a dummy outer-join tuple. If not, loop around
|
||||
* to get a new outer tuple.
|
||||
*/
|
||||
hjstate->hj_NeedNewOuter = true;
|
||||
|
||||
@@ -291,11 +281,11 @@ ExecHashJoin(HashJoin *node)
|
||||
|
||||
if (ExecQual(otherqual, econtext, false))
|
||||
{
|
||||
/* ----------------
|
||||
* qualification was satisfied so we project and
|
||||
* return the slot containing the result tuple
|
||||
* using ExecProject().
|
||||
* ----------------
|
||||
|
||||
/*
|
||||
* qualification was satisfied so we project and return
|
||||
* the slot containing the result tuple using
|
||||
* ExecProject().
|
||||
*/
|
||||
TupleTableSlot *result;
|
||||
|
||||
@@ -325,30 +315,26 @@ ExecInitHashJoin(HashJoin *node, EState *estate, Plan *parent)
|
||||
Plan *outerNode;
|
||||
Hash *hashNode;
|
||||
|
||||
/* ----------------
|
||||
* assign the node's execution state
|
||||
* ----------------
|
||||
/*
|
||||
* assign the node's execution state
|
||||
*/
|
||||
node->join.plan.state = estate;
|
||||
|
||||
/* ----------------
|
||||
/*
|
||||
* create state structure
|
||||
* ----------------
|
||||
*/
|
||||
hjstate = makeNode(HashJoinState);
|
||||
node->hashjoinstate = hjstate;
|
||||
|
||||
/* ----------------
|
||||
* Miscellaneous initialization
|
||||
/*
|
||||
* Miscellaneous initialization
|
||||
*
|
||||
* + create expression context for node
|
||||
* ----------------
|
||||
* create expression context for node
|
||||
*/
|
||||
ExecAssignExprContext(estate, &hjstate->jstate);
|
||||
|
||||
/* ----------------
|
||||
/*
|
||||
* initializes child nodes
|
||||
* ----------------
|
||||
*/
|
||||
outerNode = outerPlan((Plan *) node);
|
||||
hashNode = (Hash *) innerPlan((Plan *) node);
|
||||
@@ -357,9 +343,9 @@ ExecInitHashJoin(HashJoin *node, EState *estate, Plan *parent)
|
||||
ExecInitNode((Plan *) hashNode, estate, (Plan *) node);
|
||||
|
||||
#define HASHJOIN_NSLOTS 3
|
||||
/* ----------------
|
||||
* tuple table initialization
|
||||
* ----------------
|
||||
|
||||
/*
|
||||
* tuple table initialization
|
||||
*/
|
||||
ExecInitResultTupleSlot(estate, &hjstate->jstate);
|
||||
hjstate->hj_OuterTupleSlot = ExecInitExtraTupleSlot(estate);
|
||||
@@ -378,14 +364,12 @@ ExecInitHashJoin(HashJoin *node, EState *estate, Plan *parent)
|
||||
(int) node->join.jointype);
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* now for some voodoo. our temporary tuple slot
|
||||
* is actually the result tuple slot of the Hash node
|
||||
* (which is our inner plan). we do this because Hash
|
||||
* nodes don't return tuples via ExecProcNode() -- instead
|
||||
* the hash join node uses ExecScanHashBucket() to get
|
||||
* at the contents of the hash table. -cim 6/9/91
|
||||
* ----------------
|
||||
/*
|
||||
* now for some voodoo. our temporary tuple slot is actually the
|
||||
* result tuple slot of the Hash node (which is our inner plan). we
|
||||
* do this because Hash nodes don't return tuples via ExecProcNode()
|
||||
* -- instead the hash join node uses ExecScanHashBucket() to get at
|
||||
* the contents of the hash table. -cim 6/9/91
|
||||
*/
|
||||
{
|
||||
HashState *hashstate = hashNode->hashstate;
|
||||
@@ -394,9 +378,8 @@ ExecInitHashJoin(HashJoin *node, EState *estate, Plan *parent)
|
||||
hjstate->hj_HashTupleSlot = slot;
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* initialize tuple type and projection info
|
||||
* ----------------
|
||||
/*
|
||||
* initialize tuple type and projection info
|
||||
*/
|
||||
ExecAssignResultTypeFromTL((Plan *) node, &hjstate->jstate);
|
||||
ExecAssignProjectionInfo((Plan *) node, &hjstate->jstate);
|
||||
@@ -405,9 +388,8 @@ ExecInitHashJoin(HashJoin *node, EState *estate, Plan *parent)
|
||||
ExecGetTupType(outerNode),
|
||||
false);
|
||||
|
||||
/* ----------------
|
||||
* initialize hash-specific info
|
||||
* ----------------
|
||||
/*
|
||||
* initialize hash-specific info
|
||||
*/
|
||||
|
||||
hjstate->hj_hashdone = false;
|
||||
@@ -444,15 +426,13 @@ ExecEndHashJoin(HashJoin *node)
|
||||
{
|
||||
HashJoinState *hjstate;
|
||||
|
||||
/* ----------------
|
||||
* get info from the HashJoin state
|
||||
* ----------------
|
||||
/*
|
||||
* get info from the HashJoin state
|
||||
*/
|
||||
hjstate = node->hashjoinstate;
|
||||
|
||||
/* ----------------
|
||||
/*
|
||||
* free hash table in case we end plan before all tuples are retrieved
|
||||
* ---------------
|
||||
*/
|
||||
if (hjstate->hj_HashTable)
|
||||
{
|
||||
@@ -460,28 +440,24 @@ ExecEndHashJoin(HashJoin *node)
|
||||
hjstate->hj_HashTable = NULL;
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* Free the projection info and the scan attribute info
|
||||
/*
|
||||
* Free the projection info and the scan attribute info
|
||||
*
|
||||
* Note: we don't ExecFreeResultType(hjstate)
|
||||
* because the rule manager depends on the tupType
|
||||
* returned by ExecMain(). So for now, this
|
||||
* is freed at end-transaction time. -cim 6/2/91
|
||||
* ----------------
|
||||
* Note: we don't ExecFreeResultType(hjstate) because the rule manager
|
||||
* depends on the tupType returned by ExecMain(). So for now, this is
|
||||
* freed at end-transaction time. -cim 6/2/91
|
||||
*/
|
||||
ExecFreeProjectionInfo(&hjstate->jstate);
|
||||
ExecFreeExprContext(&hjstate->jstate);
|
||||
|
||||
/* ----------------
|
||||
/*
|
||||
* clean up subtrees
|
||||
* ----------------
|
||||
*/
|
||||
ExecEndNode(outerPlan((Plan *) node), (Plan *) node);
|
||||
ExecEndNode(innerPlan((Plan *) node), (Plan *) node);
|
||||
|
||||
/* ----------------
|
||||
* clean out the tuple table
|
||||
* ----------------
|
||||
/*
|
||||
* clean out the tuple table
|
||||
*/
|
||||
ExecClearTuple(hjstate->jstate.cs_ResultTupleSlot);
|
||||
ExecClearTuple(hjstate->hj_OuterTupleSlot);
|
||||
@@ -598,10 +574,9 @@ ExecHashJoinNewBatch(HashJoinState *hjstate)
|
||||
hashtable->outerBatchFile[newbatch - 2] = NULL;
|
||||
}
|
||||
|
||||
/* --------------
|
||||
* We can skip over any batches that are empty on either side.
|
||||
* Release associated temp files right away.
|
||||
* --------------
|
||||
/*
|
||||
* We can skip over any batches that are empty on either side. Release
|
||||
* associated temp files right away.
|
||||
*/
|
||||
while (newbatch <= nbatch &&
|
||||
(innerBatchSize[newbatch - 1] == 0L ||
|
||||
|
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/nodeIndexscan.c,v 1.58 2001/03/22 03:59:28 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/nodeIndexscan.c,v 1.59 2001/03/22 06:16:13 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -84,9 +84,8 @@ IndexNext(IndexScan *node)
|
||||
bool bBackward;
|
||||
int indexNumber;
|
||||
|
||||
/* ----------------
|
||||
* extract necessary information from index scan node
|
||||
* ----------------
|
||||
/*
|
||||
* extract necessary information from index scan node
|
||||
*/
|
||||
estate = node->scan.plan.state;
|
||||
direction = estate->es_direction;
|
||||
@@ -145,11 +144,10 @@ IndexNext(IndexScan *node)
|
||||
|
||||
tuple = &(indexstate->iss_htup);
|
||||
|
||||
/* ----------------
|
||||
* ok, now that we have what we need, fetch an index tuple.
|
||||
* if scanning this index succeeded then return the
|
||||
* appropriate heap tuple.. else return NULL.
|
||||
* ----------------
|
||||
/*
|
||||
* ok, now that we have what we need, fetch an index tuple. if
|
||||
* scanning this index succeeded then return the appropriate heap
|
||||
* tuple.. else return NULL.
|
||||
*/
|
||||
bBackward = ScanDirectionIsBackward(direction);
|
||||
if (bBackward)
|
||||
@@ -238,10 +236,10 @@ IndexNext(IndexScan *node)
|
||||
indexstate->iss_IndexPtr++;
|
||||
}
|
||||
}
|
||||
/* ----------------
|
||||
* if we get here it means the index scan failed so we
|
||||
* are at the end of the scan..
|
||||
* ----------------
|
||||
|
||||
/*
|
||||
* if we get here it means the index scan failed so we are at the end
|
||||
* of the scan..
|
||||
*/
|
||||
return ExecClearTuple(slot);
|
||||
}
|
||||
@@ -272,17 +270,15 @@ ExecIndexScan(IndexScan *node)
|
||||
{
|
||||
IndexScanState *indexstate = node->indxstate;
|
||||
|
||||
/* ----------------
|
||||
* If we have runtime keys and they've not already been set up,
|
||||
* do it now.
|
||||
* ----------------
|
||||
/*
|
||||
* If we have runtime keys and they've not already been set up, do it
|
||||
* now.
|
||||
*/
|
||||
if (indexstate->iss_RuntimeKeyInfo && !indexstate->iss_RuntimeKeysReady)
|
||||
ExecReScan((Plan *) node, NULL, NULL);
|
||||
|
||||
/* ----------------
|
||||
* use IndexNext as access method
|
||||
* ----------------
|
||||
/*
|
||||
* use IndexNext as access method
|
||||
*/
|
||||
return ExecScan(&node->scan, (ExecScanAccessMtd) IndexNext);
|
||||
}
|
||||
@@ -448,37 +444,32 @@ ExecEndIndexScan(IndexScan *node)
|
||||
indxqual = node->indxqual;
|
||||
runtimeKeyInfo = indexstate->iss_RuntimeKeyInfo;
|
||||
|
||||
/* ----------------
|
||||
* extract information from the node
|
||||
* ----------------
|
||||
/*
|
||||
* extract information from the node
|
||||
*/
|
||||
numIndices = indexstate->iss_NumIndices;
|
||||
scanKeys = indexstate->iss_ScanKeys;
|
||||
numScanKeys = indexstate->iss_NumScanKeys;
|
||||
|
||||
/* ----------------
|
||||
* Free the projection info and the scan attribute info
|
||||
/*
|
||||
* Free the projection info and the scan attribute info
|
||||
*
|
||||
* Note: we don't ExecFreeResultType(scanstate)
|
||||
* because the rule manager depends on the tupType
|
||||
* returned by ExecMain(). So for now, this
|
||||
* is freed at end-transaction time. -cim 6/2/91
|
||||
* ----------------
|
||||
* Note: we don't ExecFreeResultType(scanstate) because the rule manager
|
||||
* depends on the tupType returned by ExecMain(). So for now, this is
|
||||
* freed at end-transaction time. -cim 6/2/91
|
||||
*/
|
||||
ExecFreeProjectionInfo(&scanstate->cstate);
|
||||
ExecFreeExprContext(&scanstate->cstate);
|
||||
if (indexstate->iss_RuntimeContext)
|
||||
FreeExprContext(indexstate->iss_RuntimeContext);
|
||||
|
||||
/* ----------------
|
||||
* close the heap and index relations
|
||||
* ----------------
|
||||
/*
|
||||
* close the heap and index relations
|
||||
*/
|
||||
ExecCloseR((Plan *) node);
|
||||
|
||||
/* ----------------
|
||||
* free the scan keys used in scanning the indices
|
||||
* ----------------
|
||||
/*
|
||||
* free the scan keys used in scanning the indices
|
||||
*/
|
||||
for (i = 0; i < numIndices; i++)
|
||||
{
|
||||
@@ -498,9 +489,8 @@ ExecEndIndexScan(IndexScan *node)
|
||||
pfree(runtimeKeyInfo);
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* clear out tuple table slots
|
||||
* ----------------
|
||||
/*
|
||||
* clear out tuple table slots
|
||||
*/
|
||||
ExecClearTuple(scanstate->cstate.cs_ResultTupleSlot);
|
||||
ExecClearTuple(scanstate->css_ScanTupleSlot);
|
||||
@@ -605,50 +595,45 @@ ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent)
|
||||
HeapScanDesc currentScanDesc;
|
||||
ScanDirection direction;
|
||||
|
||||
/* ----------------
|
||||
* assign execution state to node
|
||||
* ----------------
|
||||
/*
|
||||
* assign execution state to node
|
||||
*/
|
||||
node->scan.plan.state = estate;
|
||||
|
||||
/* --------------------------------
|
||||
* Part 1) initialize scan state
|
||||
/*
|
||||
* Part 1) initialize scan state
|
||||
*
|
||||
* create new CommonScanState for node
|
||||
* --------------------------------
|
||||
* create new CommonScanState for node
|
||||
*/
|
||||
scanstate = makeNode(CommonScanState);
|
||||
node->scan.scanstate = scanstate;
|
||||
|
||||
/* ----------------
|
||||
* Miscellaneous initialization
|
||||
/*
|
||||
* Miscellaneous initialization
|
||||
*
|
||||
* + create expression context for node
|
||||
* ----------------
|
||||
* create expression context for node
|
||||
*/
|
||||
ExecAssignExprContext(estate, &scanstate->cstate);
|
||||
|
||||
#define INDEXSCAN_NSLOTS 3
|
||||
/* ----------------
|
||||
* tuple table initialization
|
||||
* ----------------
|
||||
|
||||
/*
|
||||
* tuple table initialization
|
||||
*/
|
||||
ExecInitResultTupleSlot(estate, &scanstate->cstate);
|
||||
ExecInitScanTupleSlot(estate, scanstate);
|
||||
|
||||
/* ----------------
|
||||
* initialize projection info. result type comes from scan desc
|
||||
* below..
|
||||
* ----------------
|
||||
/*
|
||||
* initialize projection info. result type comes from scan desc
|
||||
* below..
|
||||
*/
|
||||
ExecAssignProjectionInfo((Plan *) node, &scanstate->cstate);
|
||||
|
||||
/* --------------------------------
|
||||
* Part 2) initialize index scan state
|
||||
*
|
||||
* create new IndexScanState for node
|
||||
* --------------------------------
|
||||
*/
|
||||
/*
|
||||
* Part 2) initialize index scan state
|
||||
*
|
||||
* create new IndexScanState for node
|
||||
*/
|
||||
indexstate = makeNode(IndexScanState);
|
||||
indexstate->iss_NumIndices = 0;
|
||||
indexstate->iss_IndexPtr = -1;
|
||||
@@ -662,9 +647,8 @@ ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent)
|
||||
|
||||
node->indxstate = indexstate;
|
||||
|
||||
/* ----------------
|
||||
* get the index node information
|
||||
* ----------------
|
||||
/*
|
||||
* get the index node information
|
||||
*/
|
||||
indxid = node->indxid;
|
||||
numIndices = length(indxid);
|
||||
@@ -672,27 +656,24 @@ ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent)
|
||||
|
||||
CXT1_printf("ExecInitIndexScan: context is %d\n", CurrentMemoryContext);
|
||||
|
||||
/* ----------------
|
||||
* scanKeys is used to keep track of the ScanKey's. This is needed
|
||||
* because a single scan may use several indices and each index has
|
||||
* its own ScanKey.
|
||||
* ----------------
|
||||
/*
|
||||
* scanKeys is used to keep track of the ScanKey's. This is needed
|
||||
* because a single scan may use several indices and each index has
|
||||
* its own ScanKey.
|
||||
*/
|
||||
numScanKeys = (int *) palloc(numIndices * sizeof(int));
|
||||
scanKeys = (ScanKey *) palloc(numIndices * sizeof(ScanKey));
|
||||
relationDescs = (RelationPtr) palloc(numIndices * sizeof(Relation));
|
||||
scanDescs = (IndexScanDescPtr) palloc(numIndices * sizeof(IndexScanDesc));
|
||||
|
||||
/* ----------------
|
||||
* initialize space for runtime key info (may not be needed)
|
||||
* ----------------
|
||||
/*
|
||||
* initialize space for runtime key info (may not be needed)
|
||||
*/
|
||||
have_runtime_keys = false;
|
||||
runtimeKeyInfo = (int **) palloc(numIndices * sizeof(int *));
|
||||
|
||||
/* ----------------
|
||||
* build the index scan keys from the index qualification
|
||||
* ----------------
|
||||
/*
|
||||
* build the index scan keys from the index qualification
|
||||
*/
|
||||
indxqual = node->indxqual;
|
||||
for (i = 0; i < numIndices; i++)
|
||||
@@ -713,10 +694,9 @@ ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent)
|
||||
|
||||
CXT1_printf("ExecInitIndexScan: context is %d\n", CurrentMemoryContext);
|
||||
|
||||
/* ----------------
|
||||
* for each opclause in the given qual,
|
||||
* convert each qual's opclause into a single scan key
|
||||
* ----------------
|
||||
/*
|
||||
* for each opclause in the given qual, convert each qual's
|
||||
* opclause into a single scan key
|
||||
*/
|
||||
for (j = 0; j < n_keys; j++)
|
||||
{
|
||||
@@ -731,9 +711,8 @@ ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent)
|
||||
Oid opid; /* operator id used in scan */
|
||||
Datum scanvalue = 0; /* value used in scan (if const) */
|
||||
|
||||
/* ----------------
|
||||
* extract clause information from the qualification
|
||||
* ----------------
|
||||
/*
|
||||
* extract clause information from the qualification
|
||||
*/
|
||||
clause = nth(j, qual);
|
||||
|
||||
@@ -743,48 +722,46 @@ ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent)
|
||||
|
||||
opid = op->opid;
|
||||
|
||||
/* ----------------
|
||||
* Here we figure out the contents of the index qual.
|
||||
* The usual case is (var op const) or (const op var)
|
||||
* which means we form a scan key for the attribute
|
||||
* listed in the var node and use the value of the const.
|
||||
/*
|
||||
* Here we figure out the contents of the index qual. The
|
||||
* usual case is (var op const) or (const op var) which means
|
||||
* we form a scan key for the attribute listed in the var node
|
||||
* and use the value of the const.
|
||||
*
|
||||
* If we don't have a const node, then it means that
|
||||
* one of the var nodes refers to the "scan" tuple and
|
||||
* is used to determine which attribute to scan, and the
|
||||
* other expression is used to calculate the value used in
|
||||
* scanning the index.
|
||||
* If we don't have a const node, then it means that one of the
|
||||
* var nodes refers to the "scan" tuple and is used to
|
||||
* determine which attribute to scan, and the other expression
|
||||
* is used to calculate the value used in scanning the index.
|
||||
*
|
||||
* This means our index scan's scan key is a function of
|
||||
* information obtained during the execution of the plan
|
||||
* in which case we need to recalculate the index scan key
|
||||
* at run time.
|
||||
* This means our index scan's scan key is a function of
|
||||
* information obtained during the execution of the plan in
|
||||
* which case we need to recalculate the index scan key at run
|
||||
* time.
|
||||
*
|
||||
* Hence, we set have_runtime_keys to true and then set
|
||||
* the appropriate flag in run_keys to LEFT_OP or RIGHT_OP.
|
||||
* The corresponding scan keys are recomputed at run time.
|
||||
* Hence, we set have_runtime_keys to true and then set the
|
||||
* appropriate flag in run_keys to LEFT_OP or RIGHT_OP. The
|
||||
* corresponding scan keys are recomputed at run time.
|
||||
*
|
||||
* XXX Although this code *thinks* it can handle an indexqual
|
||||
* with the indexkey on either side, in fact it cannot.
|
||||
* Indexscans only work with quals that have the indexkey on
|
||||
* the left (the planner/optimizer makes sure it never passes
|
||||
* anything else). The reason: the scankey machinery has no
|
||||
* provision for distinguishing which side of the operator is
|
||||
* the indexed attribute and which is the compared-to constant.
|
||||
* It just assumes that the attribute is on the left :-(
|
||||
* XXX Although this code *thinks* it can handle an indexqual
|
||||
* with the indexkey on either side, in fact it cannot.
|
||||
* Indexscans only work with quals that have the indexkey on
|
||||
* the left (the planner/optimizer makes sure it never passes
|
||||
* anything else). The reason: the scankey machinery has no
|
||||
* provision for distinguishing which side of the operator is
|
||||
* the indexed attribute and which is the compared-to
|
||||
* constant. It just assumes that the attribute is on the left
|
||||
* :-(
|
||||
*
|
||||
* I am leaving this code able to support both ways, even though
|
||||
* half of it is dead code, on the off chance that someone will
|
||||
* fix the scankey machinery someday --- tgl 8/11/99.
|
||||
* ----------------
|
||||
* I am leaving this code able to support both ways, even though
|
||||
* half of it is dead code, on the off chance that someone
|
||||
* will fix the scankey machinery someday --- tgl 8/11/99.
|
||||
*/
|
||||
|
||||
scanvar = NO_OP;
|
||||
run_keys[j] = NO_OP;
|
||||
|
||||
/* ----------------
|
||||
* determine information in leftop
|
||||
* ----------------
|
||||
/*
|
||||
* determine information in leftop
|
||||
*/
|
||||
leftop = (Node *) get_leftop(clause);
|
||||
|
||||
@@ -795,21 +772,21 @@ ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent)
|
||||
|
||||
if (IsA(leftop, Var) &&var_is_rel((Var *) leftop))
|
||||
{
|
||||
/* ----------------
|
||||
* if the leftop is a "rel-var", then it means
|
||||
* that it is a var node which tells us which
|
||||
* attribute to use for our scan key.
|
||||
* ----------------
|
||||
|
||||
/*
|
||||
* if the leftop is a "rel-var", then it means that it is
|
||||
* a var node which tells us which attribute to use for
|
||||
* our scan key.
|
||||
*/
|
||||
varattno = ((Var *) leftop)->varattno;
|
||||
scanvar = LEFT_OP;
|
||||
}
|
||||
else if (IsA(leftop, Const))
|
||||
{
|
||||
/* ----------------
|
||||
* if the leftop is a const node then it means
|
||||
* it identifies the value to place in our scan key.
|
||||
* ----------------
|
||||
|
||||
/*
|
||||
* if the leftop is a const node then it means it
|
||||
* identifies the value to place in our scan key.
|
||||
*/
|
||||
scanvalue = ((Const *) leftop)->constvalue;
|
||||
if (((Const *) leftop)->constisnull)
|
||||
@@ -819,10 +796,9 @@ ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent)
|
||||
{
|
||||
bool isnull;
|
||||
|
||||
/* ----------------
|
||||
* if the leftop is a Param node then it means
|
||||
* it identifies the value to place in our scan key.
|
||||
* ----------------
|
||||
/*
|
||||
* if the leftop is a Param node then it means it
|
||||
* identifies the value to place in our scan key.
|
||||
*/
|
||||
|
||||
/* Life was so easy before ... subselects */
|
||||
@@ -844,19 +820,18 @@ ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent)
|
||||
}
|
||||
else
|
||||
{
|
||||
/* ----------------
|
||||
* otherwise, the leftop contains an expression evaluable
|
||||
* at runtime to figure out the value to place in our
|
||||
* scan key.
|
||||
* ----------------
|
||||
|
||||
/*
|
||||
* otherwise, the leftop contains an expression evaluable
|
||||
* at runtime to figure out the value to place in our scan
|
||||
* key.
|
||||
*/
|
||||
have_runtime_keys = true;
|
||||
run_keys[j] = LEFT_OP;
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* now determine information in rightop
|
||||
* ----------------
|
||||
/*
|
||||
* now determine information in rightop
|
||||
*/
|
||||
rightop = (Node *) get_rightop(clause);
|
||||
|
||||
@@ -867,30 +842,29 @@ ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent)
|
||||
|
||||
if (IsA(rightop, Var) &&var_is_rel((Var *) rightop))
|
||||
{
|
||||
/* ----------------
|
||||
* here we make sure only one op identifies the
|
||||
* scan-attribute...
|
||||
* ----------------
|
||||
|
||||
/*
|
||||
* here we make sure only one op identifies the
|
||||
* scan-attribute...
|
||||
*/
|
||||
if (scanvar == LEFT_OP)
|
||||
elog(ERROR, "ExecInitIndexScan: %s",
|
||||
"both left and right op's are rel-vars");
|
||||
|
||||
/* ----------------
|
||||
* if the rightop is a "rel-var", then it means
|
||||
* that it is a var node which tells us which
|
||||
* attribute to use for our scan key.
|
||||
* ----------------
|
||||
/*
|
||||
* if the rightop is a "rel-var", then it means that it is
|
||||
* a var node which tells us which attribute to use for
|
||||
* our scan key.
|
||||
*/
|
||||
varattno = ((Var *) rightop)->varattno;
|
||||
scanvar = RIGHT_OP;
|
||||
}
|
||||
else if (IsA(rightop, Const))
|
||||
{
|
||||
/* ----------------
|
||||
* if the rightop is a const node then it means
|
||||
* it identifies the value to place in our scan key.
|
||||
* ----------------
|
||||
|
||||
/*
|
||||
* if the rightop is a const node then it means it
|
||||
* identifies the value to place in our scan key.
|
||||
*/
|
||||
scanvalue = ((Const *) rightop)->constvalue;
|
||||
if (((Const *) rightop)->constisnull)
|
||||
@@ -900,10 +874,9 @@ ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent)
|
||||
{
|
||||
bool isnull;
|
||||
|
||||
/* ----------------
|
||||
* if the rightop is a Param node then it means
|
||||
* it identifies the value to place in our scan key.
|
||||
* ----------------
|
||||
/*
|
||||
* if the rightop is a Param node then it means it
|
||||
* identifies the value to place in our scan key.
|
||||
*/
|
||||
|
||||
/* Life was so easy before ... subselects */
|
||||
@@ -925,28 +898,26 @@ ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent)
|
||||
}
|
||||
else
|
||||
{
|
||||
/* ----------------
|
||||
* otherwise, the rightop contains an expression evaluable
|
||||
* at runtime to figure out the value to place in our
|
||||
* scan key.
|
||||
* ----------------
|
||||
|
||||
/*
|
||||
* otherwise, the rightop contains an expression evaluable
|
||||
* at runtime to figure out the value to place in our scan
|
||||
* key.
|
||||
*/
|
||||
have_runtime_keys = true;
|
||||
run_keys[j] = RIGHT_OP;
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* now check that at least one op tells us the scan
|
||||
* attribute...
|
||||
* ----------------
|
||||
/*
|
||||
* now check that at least one op tells us the scan
|
||||
* attribute...
|
||||
*/
|
||||
if (scanvar == NO_OP)
|
||||
elog(ERROR, "ExecInitIndexScan: %s",
|
||||
"neither leftop nor rightop refer to scan relation");
|
||||
|
||||
/* ----------------
|
||||
* initialize the scan key's fields appropriately
|
||||
* ----------------
|
||||
/*
|
||||
* initialize the scan key's fields appropriately
|
||||
*/
|
||||
ScanKeyEntryInitialize(&scan_keys[j],
|
||||
flags,
|
||||
@@ -956,9 +927,8 @@ ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent)
|
||||
scanvalue); /* constant */
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* store the key information into our arrays.
|
||||
* ----------------
|
||||
/*
|
||||
* store the key information into our arrays.
|
||||
*/
|
||||
numScanKeys[i] = n_keys;
|
||||
scanKeys[i] = scan_keys;
|
||||
@@ -972,20 +942,17 @@ ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent)
|
||||
indexstate->iss_ScanKeys = scanKeys;
|
||||
indexstate->iss_NumScanKeys = numScanKeys;
|
||||
|
||||
/* ----------------
|
||||
* If all of our keys have the form (op var const) , then we have no
|
||||
* runtime keys so we store NULL in the runtime key info.
|
||||
* Otherwise runtime key info contains an array of pointers
|
||||
* (one for each index) to arrays of flags (one for each key)
|
||||
* which indicate that the qual needs to be evaluated at runtime.
|
||||
* -cim 10/24/89
|
||||
/*
|
||||
* If all of our keys have the form (op var const) , then we have no
|
||||
* runtime keys so we store NULL in the runtime key info. Otherwise
|
||||
* runtime key info contains an array of pointers (one for each index)
|
||||
* to arrays of flags (one for each key) which indicate that the qual
|
||||
* needs to be evaluated at runtime. -cim 10/24/89
|
||||
*
|
||||
* If we do have runtime keys, we need an ExprContext to evaluate them;
|
||||
* the node's standard context won't do because we want to reset that
|
||||
* context for every tuple. So, build another context just like the
|
||||
* other one...
|
||||
* -tgl 7/11/00
|
||||
* ----------------
|
||||
* If we do have runtime keys, we need an ExprContext to evaluate them;
|
||||
* the node's standard context won't do because we want to reset that
|
||||
* context for every tuple. So, build another context just like the
|
||||
* other one... -tgl 7/11/00
|
||||
*/
|
||||
if (have_runtime_keys)
|
||||
{
|
||||
@@ -1009,18 +976,15 @@ ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent)
|
||||
pfree(runtimeKeyInfo);
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* get the range table and direction information
|
||||
* from the execution state (these are needed to
|
||||
* open the relations).
|
||||
* ----------------
|
||||
/*
|
||||
* get the range table and direction information from the execution
|
||||
* state (these are needed to open the relations).
|
||||
*/
|
||||
rangeTable = estate->es_range_table;
|
||||
direction = estate->es_direction;
|
||||
|
||||
/* ----------------
|
||||
* open the base relation
|
||||
* ----------------
|
||||
/*
|
||||
* open the base relation
|
||||
*/
|
||||
relid = node->scan.scanrelid;
|
||||
rtentry = rt_fetch(relid, rangeTable);
|
||||
@@ -1040,17 +1004,15 @@ ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent)
|
||||
scanstate->css_currentRelation = currentRelation;
|
||||
scanstate->css_currentScanDesc = currentScanDesc;
|
||||
|
||||
/* ----------------
|
||||
* get the scan type from the relation descriptor.
|
||||
* ----------------
|
||||
/*
|
||||
* get the scan type from the relation descriptor.
|
||||
*/
|
||||
ExecAssignScanType(scanstate, RelationGetDescr(currentRelation), false);
|
||||
ExecAssignResultTypeFromTL((Plan *) node, &scanstate->cstate);
|
||||
|
||||
/* ----------------
|
||||
* open the index relations and initialize
|
||||
* relation and scan descriptors.
|
||||
* ----------------
|
||||
/*
|
||||
* open the index relations and initialize relation and scan
|
||||
* descriptors.
|
||||
*/
|
||||
for (i = 0; i < numIndices; i++)
|
||||
{
|
||||
@@ -1073,9 +1035,8 @@ ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent)
|
||||
indexstate->iss_RelationDescs = relationDescs;
|
||||
indexstate->iss_ScanDescs = scanDescs;
|
||||
|
||||
/* ----------------
|
||||
* all done.
|
||||
* ----------------
|
||||
/*
|
||||
* all done.
|
||||
*/
|
||||
return TRUE;
|
||||
}
|
||||
|
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/nodeLimit.c,v 1.4 2001/03/22 03:59:28 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/nodeLimit.c,v 1.5 2001/03/22 06:16:13 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -44,46 +44,43 @@ ExecLimit(Limit *node)
|
||||
Plan *outerPlan;
|
||||
long netlimit;
|
||||
|
||||
/* ----------------
|
||||
* get information from the node
|
||||
* ----------------
|
||||
/*
|
||||
* get information from the node
|
||||
*/
|
||||
limitstate = node->limitstate;
|
||||
direction = node->plan.state->es_direction;
|
||||
outerPlan = outerPlan((Plan *) node);
|
||||
resultTupleSlot = limitstate->cstate.cs_ResultTupleSlot;
|
||||
|
||||
/* ----------------
|
||||
* If first call for this scan, compute limit/offset.
|
||||
* (We can't do this any earlier, because parameters from upper nodes
|
||||
* may not be set until now.)
|
||||
* ----------------
|
||||
/*
|
||||
* If first call for this scan, compute limit/offset. (We can't do
|
||||
* this any earlier, because parameters from upper nodes may not be
|
||||
* set until now.)
|
||||
*/
|
||||
if (!limitstate->parmsSet)
|
||||
recompute_limits(node);
|
||||
netlimit = limitstate->offset + limitstate->count;
|
||||
|
||||
/* ----------------
|
||||
* now loop, returning only desired tuples.
|
||||
* ----------------
|
||||
/*
|
||||
* now loop, returning only desired tuples.
|
||||
*/
|
||||
for (;;)
|
||||
{
|
||||
/*----------------
|
||||
* If we have reached the subplan EOF or the limit, just quit.
|
||||
|
||||
/*
|
||||
* If we have reached the subplan EOF or the limit, just quit.
|
||||
*
|
||||
* NOTE: when scanning forwards, we must fetch one tuple beyond the
|
||||
* COUNT limit before we can return NULL, else the subplan won't be
|
||||
* properly positioned to start going backwards. Hence test here
|
||||
* is for position > netlimit not position >= netlimit.
|
||||
* COUNT limit before we can return NULL, else the subplan won't
|
||||
* be properly positioned to start going backwards. Hence test
|
||||
* here is for position > netlimit not position >= netlimit.
|
||||
*
|
||||
* Similarly, when scanning backwards, we must re-fetch the last
|
||||
* tuple in the offset region before we can return NULL. Otherwise
|
||||
* we won't be correctly aligned to start going forward again. So,
|
||||
* although you might think we can quit when position = offset + 1,
|
||||
* we have to fetch a subplan tuple first, and then exit when
|
||||
* position = offset.
|
||||
*----------------
|
||||
* tuple in the offset region before we can return NULL.
|
||||
* Otherwise we won't be correctly aligned to start going forward
|
||||
* again. So, although you might think we can quit when position
|
||||
* = offset + 1, we have to fetch a subplan tuple first, and then
|
||||
* exit when position = offset.
|
||||
*/
|
||||
if (ScanDirectionIsForward(direction))
|
||||
{
|
||||
@@ -97,9 +94,9 @@ ExecLimit(Limit *node)
|
||||
if (limitstate->position <= limitstate->offset)
|
||||
return NULL;
|
||||
}
|
||||
/* ----------------
|
||||
* fetch a tuple from the outer subplan
|
||||
* ----------------
|
||||
|
||||
/*
|
||||
* fetch a tuple from the outer subplan
|
||||
*/
|
||||
slot = ExecProcNode(outerPlan, (Plan *) node);
|
||||
if (TupIsNull(slot))
|
||||
@@ -136,10 +133,9 @@ ExecLimit(Limit *node)
|
||||
}
|
||||
limitstate->atEnd = false;
|
||||
|
||||
/* ----------------
|
||||
* Now, is this a tuple we want? If not, loop around to fetch
|
||||
* another tuple from the subplan.
|
||||
* ----------------
|
||||
/*
|
||||
* Now, is this a tuple we want? If not, loop around to fetch
|
||||
* another tuple from the subplan.
|
||||
*/
|
||||
if (limitstate->position > limitstate->offset &&
|
||||
(limitstate->noCount || limitstate->position <= netlimit))
|
||||
@@ -224,47 +220,42 @@ ExecInitLimit(Limit *node, EState *estate, Plan *parent)
|
||||
LimitState *limitstate;
|
||||
Plan *outerPlan;
|
||||
|
||||
/* ----------------
|
||||
* assign execution state to node
|
||||
* ----------------
|
||||
/*
|
||||
* assign execution state to node
|
||||
*/
|
||||
node->plan.state = estate;
|
||||
|
||||
/* ----------------
|
||||
* create new LimitState for node
|
||||
* ----------------
|
||||
/*
|
||||
* create new LimitState for node
|
||||
*/
|
||||
limitstate = makeNode(LimitState);
|
||||
node->limitstate = limitstate;
|
||||
limitstate->parmsSet = false;
|
||||
|
||||
/* ----------------
|
||||
* Miscellaneous initialization
|
||||
/*
|
||||
* Miscellaneous initialization
|
||||
*
|
||||
* Limit nodes never call ExecQual or ExecProject, but they need
|
||||
* an exprcontext anyway to evaluate the limit/offset parameters in.
|
||||
* ----------------
|
||||
* Limit nodes never call ExecQual or ExecProject, but they need an
|
||||
* exprcontext anyway to evaluate the limit/offset parameters in.
|
||||
*/
|
||||
ExecAssignExprContext(estate, &limitstate->cstate);
|
||||
|
||||
#define LIMIT_NSLOTS 1
|
||||
/* ------------
|
||||
|
||||
/*
|
||||
* Tuple table initialization
|
||||
* ------------
|
||||
*/
|
||||
ExecInitResultTupleSlot(estate, &limitstate->cstate);
|
||||
|
||||
/* ----------------
|
||||
* then initialize outer plan
|
||||
* ----------------
|
||||
/*
|
||||
* then initialize outer plan
|
||||
*/
|
||||
outerPlan = outerPlan((Plan *) node);
|
||||
ExecInitNode(outerPlan, estate, (Plan *) node);
|
||||
|
||||
/* ----------------
|
||||
* limit nodes do no projections, so initialize
|
||||
* projection info for this node appropriately
|
||||
* ----------------
|
||||
/*
|
||||
* limit nodes do no projections, so initialize projection info for
|
||||
* this node appropriately
|
||||
*/
|
||||
ExecAssignResultTypeFromOuterPlan((Plan *) node, &limitstate->cstate);
|
||||
limitstate->cstate.cs_ProjInfo = NULL;
|
||||
|
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/nodeMaterial.c,v 1.34 2001/03/22 03:59:28 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/nodeMaterial.c,v 1.35 2001/03/22 06:16:13 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -53,46 +53,41 @@ ExecMaterial(Material *node)
|
||||
TupleTableSlot *slot;
|
||||
bool should_free;
|
||||
|
||||
/* ----------------
|
||||
* get state info from node
|
||||
* ----------------
|
||||
/*
|
||||
* get state info from node
|
||||
*/
|
||||
matstate = node->matstate;
|
||||
estate = node->plan.state;
|
||||
dir = estate->es_direction;
|
||||
tuplestorestate = (Tuplestorestate *) matstate->tuplestorestate;
|
||||
|
||||
/* ----------------
|
||||
* If first time through, read all tuples from outer plan and
|
||||
* pass them to tuplestore.c.
|
||||
* Subsequent calls just fetch tuples from tuplestore.
|
||||
* ----------------
|
||||
/*
|
||||
* If first time through, read all tuples from outer plan and pass
|
||||
* them to tuplestore.c. Subsequent calls just fetch tuples from
|
||||
* tuplestore.
|
||||
*/
|
||||
|
||||
if (tuplestorestate == NULL)
|
||||
{
|
||||
Plan *outerNode;
|
||||
|
||||
/* ----------------
|
||||
* Want to scan subplan in the forward direction while creating
|
||||
* the stored data. (Does setting my direction actually affect
|
||||
* the subplan? I bet this is useless code...)
|
||||
* ----------------
|
||||
/*
|
||||
* Want to scan subplan in the forward direction while creating
|
||||
* the stored data. (Does setting my direction actually affect
|
||||
* the subplan? I bet this is useless code...)
|
||||
*/
|
||||
estate->es_direction = ForwardScanDirection;
|
||||
|
||||
/* ----------------
|
||||
* Initialize tuplestore module.
|
||||
* ----------------
|
||||
/*
|
||||
* Initialize tuplestore module.
|
||||
*/
|
||||
tuplestorestate = tuplestore_begin_heap(true, /* randomAccess */
|
||||
SortMem);
|
||||
|
||||
matstate->tuplestorestate = (void *) tuplestorestate;
|
||||
|
||||
/* ----------------
|
||||
* Scan the subplan and feed all the tuples to tuplestore.
|
||||
* ----------------
|
||||
/*
|
||||
* Scan the subplan and feed all the tuples to tuplestore.
|
||||
*/
|
||||
outerNode = outerPlan((Plan *) node);
|
||||
|
||||
@@ -107,23 +102,20 @@ ExecMaterial(Material *node)
|
||||
ExecClearTuple(slot);
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* Complete the store.
|
||||
* ----------------
|
||||
/*
|
||||
* Complete the store.
|
||||
*/
|
||||
tuplestore_donestoring(tuplestorestate);
|
||||
|
||||
/* ----------------
|
||||
* restore to user specified direction
|
||||
* ----------------
|
||||
/*
|
||||
* restore to user specified direction
|
||||
*/
|
||||
estate->es_direction = dir;
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* Get the first or next tuple from tuplestore.
|
||||
* Returns NULL if no more tuples.
|
||||
* ----------------
|
||||
/*
|
||||
* Get the first or next tuple from tuplestore. Returns NULL if no
|
||||
* more tuples.
|
||||
*/
|
||||
slot = (TupleTableSlot *) matstate->csstate.cstate.cs_ResultTupleSlot;
|
||||
heapTuple = tuplestore_getheaptuple(tuplestorestate,
|
||||
@@ -143,50 +135,44 @@ ExecInitMaterial(Material *node, EState *estate, Plan *parent)
|
||||
MaterialState *matstate;
|
||||
Plan *outerPlan;
|
||||
|
||||
/* ----------------
|
||||
* assign the node's execution state
|
||||
* ----------------
|
||||
/*
|
||||
* assign the node's execution state
|
||||
*/
|
||||
node->plan.state = estate;
|
||||
|
||||
/* ----------------
|
||||
/*
|
||||
* create state structure
|
||||
* ----------------
|
||||
*/
|
||||
matstate = makeNode(MaterialState);
|
||||
matstate->tuplestorestate = NULL;
|
||||
node->matstate = matstate;
|
||||
|
||||
/* ----------------
|
||||
* Miscellaneous initialization
|
||||
/*
|
||||
* Miscellaneous initialization
|
||||
*
|
||||
* Materialization nodes don't need ExprContexts because
|
||||
* they never call ExecQual or ExecProject.
|
||||
* ----------------
|
||||
* Materialization nodes don't need ExprContexts because they never call
|
||||
* ExecQual or ExecProject.
|
||||
*/
|
||||
|
||||
#define MATERIAL_NSLOTS 1
|
||||
/* ----------------
|
||||
|
||||
/*
|
||||
* tuple table initialization
|
||||
*
|
||||
* material nodes only return tuples from their materialized
|
||||
* relation.
|
||||
* ----------------
|
||||
* material nodes only return tuples from their materialized relation.
|
||||
*/
|
||||
ExecInitResultTupleSlot(estate, &matstate->csstate.cstate);
|
||||
ExecInitScanTupleSlot(estate, &matstate->csstate);
|
||||
|
||||
/* ----------------
|
||||
/*
|
||||
* initializes child nodes
|
||||
* ----------------
|
||||
*/
|
||||
outerPlan = outerPlan((Plan *) node);
|
||||
ExecInitNode(outerPlan, estate, (Plan *) node);
|
||||
|
||||
/* ----------------
|
||||
* initialize tuple type. no need to initialize projection
|
||||
* info because this node doesn't do projections.
|
||||
* ----------------
|
||||
/*
|
||||
* initialize tuple type. no need to initialize projection info
|
||||
* because this node doesn't do projections.
|
||||
*/
|
||||
ExecAssignResultTypeFromOuterPlan((Plan *) node, &matstate->csstate.cstate);
|
||||
ExecAssignScanTypeFromOuterPlan((Plan *) node, &matstate->csstate);
|
||||
@@ -213,28 +199,24 @@ ExecEndMaterial(Material *node)
|
||||
MaterialState *matstate;
|
||||
Plan *outerPlan;
|
||||
|
||||
/* ----------------
|
||||
* get info from the material state
|
||||
* ----------------
|
||||
/*
|
||||
* get info from the material state
|
||||
*/
|
||||
matstate = node->matstate;
|
||||
|
||||
/* ----------------
|
||||
* shut down the subplan
|
||||
* ----------------
|
||||
/*
|
||||
* shut down the subplan
|
||||
*/
|
||||
outerPlan = outerPlan((Plan *) node);
|
||||
ExecEndNode(outerPlan, (Plan *) node);
|
||||
|
||||
/* ----------------
|
||||
* clean out the tuple table
|
||||
* ----------------
|
||||
/*
|
||||
* clean out the tuple table
|
||||
*/
|
||||
ExecClearTuple(matstate->csstate.css_ScanTupleSlot);
|
||||
|
||||
/* ----------------
|
||||
* Release tuplestore resources
|
||||
* ----------------
|
||||
/*
|
||||
* Release tuplestore resources
|
||||
*/
|
||||
if (matstate->tuplestorestate != NULL)
|
||||
tuplestore_end((Tuplestorestate *) matstate->tuplestorestate);
|
||||
@@ -252,9 +234,8 @@ ExecMaterialMarkPos(Material *node)
|
||||
{
|
||||
MaterialState *matstate = node->matstate;
|
||||
|
||||
/* ----------------
|
||||
* if we haven't materialized yet, just return.
|
||||
* ----------------
|
||||
/*
|
||||
* if we haven't materialized yet, just return.
|
||||
*/
|
||||
if (!matstate->tuplestorestate)
|
||||
return;
|
||||
@@ -273,16 +254,14 @@ ExecMaterialRestrPos(Material *node)
|
||||
{
|
||||
MaterialState *matstate = node->matstate;
|
||||
|
||||
/* ----------------
|
||||
* if we haven't materialized yet, just return.
|
||||
* ----------------
|
||||
/*
|
||||
* if we haven't materialized yet, just return.
|
||||
*/
|
||||
if (!matstate->tuplestorestate)
|
||||
return;
|
||||
|
||||
/* ----------------
|
||||
* restore the scan to the previously marked position
|
||||
* ----------------
|
||||
/*
|
||||
* restore the scan to the previously marked position
|
||||
*/
|
||||
tuplestore_restorepos((Tuplestorestate *) matstate->tuplestorestate);
|
||||
}
|
||||
|
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/nodeMergejoin.c,v 1.43 2001/03/22 03:59:29 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/nodeMergejoin.c,v 1.44 2001/03/22 06:16:13 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -114,38 +114,36 @@ MJFormSkipQual(List *qualList, char *replaceopname)
|
||||
Oid oprleft,
|
||||
oprright;
|
||||
|
||||
/* ----------------
|
||||
* qualList is a list: ((op .. ..) ...)
|
||||
* first we make a copy of it. copyObject() makes a deep copy
|
||||
* so let's use it instead of the old fashoned lispCopy()...
|
||||
* ----------------
|
||||
/*
|
||||
* qualList is a list: ((op .. ..) ...)
|
||||
*
|
||||
* first we make a copy of it. copyObject() makes a deep copy so let's
|
||||
* use it instead of the old fashoned lispCopy()...
|
||||
*/
|
||||
qualCopy = (List *) copyObject((Node *) qualList);
|
||||
|
||||
foreach(qualcdr, qualCopy)
|
||||
{
|
||||
/* ----------------
|
||||
* first get the current (op .. ..) list
|
||||
* ----------------
|
||||
|
||||
/*
|
||||
* first get the current (op .. ..) list
|
||||
*/
|
||||
qual = lfirst(qualcdr);
|
||||
|
||||
/* ----------------
|
||||
* now get at the op
|
||||
* ----------------
|
||||
/*
|
||||
* now get at the op
|
||||
*/
|
||||
op = (Oper *) qual->oper;
|
||||
if (!IsA(op, Oper))
|
||||
elog(ERROR, "MJFormSkipQual: op not an Oper!");
|
||||
|
||||
/* ----------------
|
||||
* Get the declared left and right operand types of the operator.
|
||||
* Note we do *not* use the actual operand types, since those might
|
||||
* be different in scenarios with binary-compatible data types.
|
||||
* There should be "<" and ">" operators matching a mergejoinable
|
||||
* "=" operator's declared operand types, but we might not find them
|
||||
* if we search with the actual operand types.
|
||||
* ----------------
|
||||
/*
|
||||
* Get the declared left and right operand types of the operator.
|
||||
* Note we do *not* use the actual operand types, since those
|
||||
* might be different in scenarios with binary-compatible data
|
||||
* types. There should be "<" and ">" operators matching a
|
||||
* mergejoinable "=" operator's declared operand types, but we
|
||||
* might not find them if we search with the actual operand types.
|
||||
*/
|
||||
optup = SearchSysCache(OPEROID,
|
||||
ObjectIdGetDatum(op->opno),
|
||||
@@ -157,10 +155,9 @@ MJFormSkipQual(List *qualList, char *replaceopname)
|
||||
oprright = opform->oprright;
|
||||
ReleaseSysCache(optup);
|
||||
|
||||
/* ----------------
|
||||
* Now look up the matching "<" or ">" operator. If there isn't one,
|
||||
* whoever marked the "=" operator mergejoinable was a loser.
|
||||
* ----------------
|
||||
/*
|
||||
* Now look up the matching "<" or ">" operator. If there isn't
|
||||
* one, whoever marked the "=" operator mergejoinable was a loser.
|
||||
*/
|
||||
optup = SearchSysCache(OPERNAME,
|
||||
PointerGetDatum(replaceopname),
|
||||
@@ -173,9 +170,8 @@ MJFormSkipQual(List *qualList, char *replaceopname)
|
||||
op->opno, replaceopname);
|
||||
opform = (Form_pg_operator) GETSTRUCT(optup);
|
||||
|
||||
/* ----------------
|
||||
* And replace the data in the copied operator node.
|
||||
* ----------------
|
||||
/*
|
||||
* And replace the data in the copied operator node.
|
||||
*/
|
||||
op->opno = optup->t_data->t_oid;
|
||||
op->opid = opform->oprcode;
|
||||
@@ -216,12 +212,10 @@ MergeCompare(List *eqQual, List *compareQual, ExprContext *econtext)
|
||||
*/
|
||||
oldContext = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);
|
||||
|
||||
/* ----------------
|
||||
* for each pair of clauses, test them until
|
||||
* our compare conditions are satisfied.
|
||||
* if we reach the end of the list, none of our key greater-than
|
||||
* conditions were satisfied so we return false.
|
||||
* ----------------
|
||||
/*
|
||||
* for each pair of clauses, test them until our compare conditions
|
||||
* are satisfied. if we reach the end of the list, none of our key
|
||||
* greater-than conditions were satisfied so we return false.
|
||||
*/
|
||||
result = false; /* assume 'false' result */
|
||||
|
||||
@@ -231,12 +225,11 @@ MergeCompare(List *eqQual, List *compareQual, ExprContext *econtext)
|
||||
Datum const_value;
|
||||
bool isNull;
|
||||
|
||||
/* ----------------
|
||||
* first test if our compare clause is satisfied.
|
||||
* if so then return true.
|
||||
/*
|
||||
* first test if our compare clause is satisfied. if so then
|
||||
* return true.
|
||||
*
|
||||
* A NULL result is considered false.
|
||||
* ----------------
|
||||
* A NULL result is considered false.
|
||||
*/
|
||||
const_value = ExecEvalExpr((Node *) lfirst(clause), econtext,
|
||||
&isNull, NULL);
|
||||
@@ -247,11 +240,10 @@ MergeCompare(List *eqQual, List *compareQual, ExprContext *econtext)
|
||||
break;
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* ok, the compare clause failed so we test if the keys
|
||||
* are equal... if key1 != key2, we return false.
|
||||
* otherwise key1 = key2 so we move on to the next pair of keys.
|
||||
* ----------------
|
||||
/*
|
||||
* ok, the compare clause failed so we test if the keys are
|
||||
* equal... if key1 != key2, we return false. otherwise key1 =
|
||||
* key2 so we move on to the next pair of keys.
|
||||
*/
|
||||
const_value = ExecEvalExpr((Node *) lfirst(eqclause),
|
||||
econtext,
|
||||
@@ -404,9 +396,8 @@ ExecMergeJoin(MergeJoin *node)
|
||||
bool doFillOuter;
|
||||
bool doFillInner;
|
||||
|
||||
/* ----------------
|
||||
* get information from node
|
||||
* ----------------
|
||||
/*
|
||||
* get information from node
|
||||
*/
|
||||
mergestate = node->mergestate;
|
||||
estate = node->join.plan.state;
|
||||
@@ -455,11 +446,10 @@ ExecMergeJoin(MergeJoin *node)
|
||||
innerSkipQual = mergestate->mj_OuterSkipQual;
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* Check to see if we're still projecting out tuples from a previous
|
||||
* join tuple (because there is a function-returning-set in the
|
||||
* projection expressions). If so, try to project another one.
|
||||
* ----------------
|
||||
/*
|
||||
* Check to see if we're still projecting out tuples from a previous
|
||||
* join tuple (because there is a function-returning-set in the
|
||||
* projection expressions). If so, try to project another one.
|
||||
*/
|
||||
if (mergestate->jstate.cs_TupFromTlist)
|
||||
{
|
||||
@@ -473,25 +463,23 @@ ExecMergeJoin(MergeJoin *node)
|
||||
mergestate->jstate.cs_TupFromTlist = false;
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* Reset per-tuple memory context to free any expression evaluation
|
||||
* storage allocated in the previous tuple cycle. Note this can't
|
||||
* happen until we're done projecting out tuples from a join tuple.
|
||||
* ----------------
|
||||
/*
|
||||
* Reset per-tuple memory context to free any expression evaluation
|
||||
* storage allocated in the previous tuple cycle. Note this can't
|
||||
* happen until we're done projecting out tuples from a join tuple.
|
||||
*/
|
||||
ResetExprContext(econtext);
|
||||
|
||||
/* ----------------
|
||||
* ok, everything is setup.. let's go to work
|
||||
* ----------------
|
||||
/*
|
||||
* ok, everything is setup.. let's go to work
|
||||
*/
|
||||
for (;;)
|
||||
{
|
||||
/* ----------------
|
||||
* get the current state of the join and do things accordingly.
|
||||
* Note: The join states are highlighted with 32-* comments for
|
||||
* improved readability.
|
||||
* ----------------
|
||||
|
||||
/*
|
||||
* get the current state of the join and do things accordingly.
|
||||
* Note: The join states are highlighted with 32-* comments for
|
||||
* improved readability.
|
||||
*/
|
||||
MJ_dump(mergestate);
|
||||
|
||||
@@ -553,10 +541,9 @@ ExecMergeJoin(MergeJoin *node)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* OK, we have the initial tuples. Begin by skipping
|
||||
* unmatched inner tuples.
|
||||
* ----------------
|
||||
/*
|
||||
* OK, we have the initial tuples. Begin by skipping
|
||||
* unmatched inner tuples.
|
||||
*/
|
||||
mergestate->mj_JoinState = EXEC_MJ_SKIPINNER_BEGIN;
|
||||
break;
|
||||
@@ -644,10 +631,11 @@ ExecMergeJoin(MergeJoin *node)
|
||||
|
||||
if (qualResult)
|
||||
{
|
||||
/* ----------------
|
||||
* qualification succeeded. now form the desired
|
||||
* projection tuple and return the slot containing it.
|
||||
* ----------------
|
||||
|
||||
/*
|
||||
* qualification succeeded. now form the desired
|
||||
* projection tuple and return the slot containing
|
||||
* it.
|
||||
*/
|
||||
TupleTableSlot *result;
|
||||
ExprDoneCond isDone;
|
||||
@@ -697,10 +685,11 @@ ExecMergeJoin(MergeJoin *node)
|
||||
|
||||
if (ExecQual(otherqual, econtext, false))
|
||||
{
|
||||
/* ----------------
|
||||
* qualification succeeded. now form the desired
|
||||
* projection tuple and return the slot containing it.
|
||||
* ----------------
|
||||
|
||||
/*
|
||||
* qualification succeeded. now form the desired
|
||||
* projection tuple and return the slot containing
|
||||
* it.
|
||||
*/
|
||||
TupleTableSlot *result;
|
||||
ExprDoneCond isDone;
|
||||
@@ -719,9 +708,8 @@ ExecMergeJoin(MergeJoin *node)
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* now we get the next inner tuple, if any
|
||||
* ----------------
|
||||
/*
|
||||
* now we get the next inner tuple, if any
|
||||
*/
|
||||
innerTupleSlot = ExecProcNode(innerPlan, (Plan *) node);
|
||||
mergestate->mj_InnerTupleSlot = innerTupleSlot;
|
||||
@@ -775,10 +763,11 @@ ExecMergeJoin(MergeJoin *node)
|
||||
|
||||
if (ExecQual(otherqual, econtext, false))
|
||||
{
|
||||
/* ----------------
|
||||
* qualification succeeded. now form the desired
|
||||
* projection tuple and return the slot containing it.
|
||||
* ----------------
|
||||
|
||||
/*
|
||||
* qualification succeeded. now form the desired
|
||||
* projection tuple and return the slot containing
|
||||
* it.
|
||||
*/
|
||||
TupleTableSlot *result;
|
||||
ExprDoneCond isDone;
|
||||
@@ -797,19 +786,17 @@ ExecMergeJoin(MergeJoin *node)
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* now we get the next outer tuple, if any
|
||||
* ----------------
|
||||
/*
|
||||
* now we get the next outer tuple, if any
|
||||
*/
|
||||
outerTupleSlot = ExecProcNode(outerPlan, (Plan *) node);
|
||||
mergestate->mj_OuterTupleSlot = outerTupleSlot;
|
||||
MJ_DEBUG_PROC_NODE(outerTupleSlot);
|
||||
mergestate->mj_MatchedOuter = false;
|
||||
|
||||
/* ----------------
|
||||
* if the outer tuple is null then we are done with the
|
||||
* join, unless we have inner tuples we need to null-fill.
|
||||
* ----------------
|
||||
/*
|
||||
* if the outer tuple is null then we are done with the
|
||||
* join, unless we have inner tuples we need to null-fill.
|
||||
*/
|
||||
if (TupIsNull(outerTupleSlot))
|
||||
{
|
||||
@@ -869,9 +856,9 @@ ExecMergeJoin(MergeJoin *node)
|
||||
case EXEC_MJ_TESTOUTER:
|
||||
MJ_printf("ExecMergeJoin: EXEC_MJ_TESTOUTER\n");
|
||||
|
||||
/* ----------------
|
||||
* here we compare the outer tuple with the marked inner tuple
|
||||
* ----------------
|
||||
/*
|
||||
* here we compare the outer tuple with the marked inner
|
||||
* tuple
|
||||
*/
|
||||
ResetExprContext(econtext);
|
||||
|
||||
@@ -967,11 +954,10 @@ ExecMergeJoin(MergeJoin *node)
|
||||
case EXEC_MJ_SKIPOUTER_BEGIN:
|
||||
MJ_printf("ExecMergeJoin: EXEC_MJ_SKIPOUTER_BEGIN\n");
|
||||
|
||||
/* ----------------
|
||||
* before we advance, make sure the current tuples
|
||||
* do not satisfy the mergeclauses. If they do, then
|
||||
* we update the marked tuple and go join them.
|
||||
* ----------------
|
||||
/*
|
||||
* before we advance, make sure the current tuples do not
|
||||
* satisfy the mergeclauses. If they do, then we update
|
||||
* the marked tuple and go join them.
|
||||
*/
|
||||
ResetExprContext(econtext);
|
||||
|
||||
@@ -999,9 +985,8 @@ ExecMergeJoin(MergeJoin *node)
|
||||
case EXEC_MJ_SKIPOUTER_TEST:
|
||||
MJ_printf("ExecMergeJoin: EXEC_MJ_SKIPOUTER_TEST\n");
|
||||
|
||||
/* ----------------
|
||||
* ok, now test the skip qualification
|
||||
* ----------------
|
||||
/*
|
||||
* ok, now test the skip qualification
|
||||
*/
|
||||
outerTupleSlot = mergestate->mj_OuterTupleSlot;
|
||||
econtext->ecxt_outertuple = outerTupleSlot;
|
||||
@@ -1014,10 +999,9 @@ ExecMergeJoin(MergeJoin *node)
|
||||
|
||||
MJ_DEBUG_MERGE_COMPARE(outerSkipQual, compareResult);
|
||||
|
||||
/* ----------------
|
||||
* compareResult is true as long as we should
|
||||
* continue skipping outer tuples.
|
||||
* ----------------
|
||||
/*
|
||||
* compareResult is true as long as we should continue
|
||||
* skipping outer tuples.
|
||||
*/
|
||||
if (compareResult)
|
||||
{
|
||||
@@ -1025,12 +1009,10 @@ ExecMergeJoin(MergeJoin *node)
|
||||
break;
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* now check the inner skip qual to see if we
|
||||
* should now skip inner tuples... if we fail the
|
||||
* inner skip qual, then we know we have a new pair
|
||||
* of matching tuples.
|
||||
* ----------------
|
||||
/*
|
||||
* now check the inner skip qual to see if we should now
|
||||
* skip inner tuples... if we fail the inner skip qual,
|
||||
* then we know we have a new pair of matching tuples.
|
||||
*/
|
||||
compareResult = MergeCompare(mergeclauses,
|
||||
innerSkipQual,
|
||||
@@ -1044,10 +1026,9 @@ ExecMergeJoin(MergeJoin *node)
|
||||
mergestate->mj_JoinState = EXEC_MJ_JOINMARK;
|
||||
break;
|
||||
|
||||
/*------------------------------------------------
|
||||
/*
|
||||
* Before advancing, we check to see if we must emit an
|
||||
* outer-join fill tuple for this outer tuple.
|
||||
*------------------------------------------------
|
||||
*/
|
||||
case EXEC_MJ_SKIPOUTER_ADVANCE:
|
||||
MJ_printf("ExecMergeJoin: EXEC_MJ_SKIPOUTER_ADVANCE\n");
|
||||
@@ -1071,10 +1052,11 @@ ExecMergeJoin(MergeJoin *node)
|
||||
|
||||
if (ExecQual(otherqual, econtext, false))
|
||||
{
|
||||
/* ----------------
|
||||
* qualification succeeded. now form the desired
|
||||
* projection tuple and return the slot containing it.
|
||||
* ----------------
|
||||
|
||||
/*
|
||||
* qualification succeeded. now form the desired
|
||||
* projection tuple and return the slot containing
|
||||
* it.
|
||||
*/
|
||||
TupleTableSlot *result;
|
||||
ExprDoneCond isDone;
|
||||
@@ -1093,19 +1075,17 @@ ExecMergeJoin(MergeJoin *node)
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* now we get the next outer tuple, if any
|
||||
* ----------------
|
||||
/*
|
||||
* now we get the next outer tuple, if any
|
||||
*/
|
||||
outerTupleSlot = ExecProcNode(outerPlan, (Plan *) node);
|
||||
mergestate->mj_OuterTupleSlot = outerTupleSlot;
|
||||
MJ_DEBUG_PROC_NODE(outerTupleSlot);
|
||||
mergestate->mj_MatchedOuter = false;
|
||||
|
||||
/* ----------------
|
||||
* if the outer tuple is null then we are done with the
|
||||
* join, unless we have inner tuples we need to null-fill.
|
||||
* ----------------
|
||||
/*
|
||||
* if the outer tuple is null then we are done with the
|
||||
* join, unless we have inner tuples we need to null-fill.
|
||||
*/
|
||||
if (TupIsNull(outerTupleSlot))
|
||||
{
|
||||
@@ -1125,9 +1105,8 @@ ExecMergeJoin(MergeJoin *node)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* otherwise test the new tuple against the skip qual.
|
||||
* ----------------
|
||||
/*
|
||||
* otherwise test the new tuple against the skip qual.
|
||||
*/
|
||||
mergestate->mj_JoinState = EXEC_MJ_SKIPOUTER_TEST;
|
||||
break;
|
||||
@@ -1155,11 +1134,10 @@ ExecMergeJoin(MergeJoin *node)
|
||||
case EXEC_MJ_SKIPINNER_BEGIN:
|
||||
MJ_printf("ExecMergeJoin: EXEC_MJ_SKIPINNER_BEGIN\n");
|
||||
|
||||
/* ----------------
|
||||
* before we advance, make sure the current tuples
|
||||
* do not satisfy the mergeclauses. If they do, then
|
||||
* we update the marked tuple and go join them.
|
||||
* ----------------
|
||||
/*
|
||||
* before we advance, make sure the current tuples do not
|
||||
* satisfy the mergeclauses. If they do, then we update
|
||||
* the marked tuple and go join them.
|
||||
*/
|
||||
ResetExprContext(econtext);
|
||||
|
||||
@@ -1187,9 +1165,8 @@ ExecMergeJoin(MergeJoin *node)
|
||||
case EXEC_MJ_SKIPINNER_TEST:
|
||||
MJ_printf("ExecMergeJoin: EXEC_MJ_SKIPINNER_TEST\n");
|
||||
|
||||
/* ----------------
|
||||
* ok, now test the skip qualification
|
||||
* ----------------
|
||||
/*
|
||||
* ok, now test the skip qualification
|
||||
*/
|
||||
outerTupleSlot = mergestate->mj_OuterTupleSlot;
|
||||
econtext->ecxt_outertuple = outerTupleSlot;
|
||||
@@ -1202,10 +1179,9 @@ ExecMergeJoin(MergeJoin *node)
|
||||
|
||||
MJ_DEBUG_MERGE_COMPARE(innerSkipQual, compareResult);
|
||||
|
||||
/* ----------------
|
||||
* compareResult is true as long as we should
|
||||
* continue skipping inner tuples.
|
||||
* ----------------
|
||||
/*
|
||||
* compareResult is true as long as we should continue
|
||||
* skipping inner tuples.
|
||||
*/
|
||||
if (compareResult)
|
||||
{
|
||||
@@ -1213,12 +1189,10 @@ ExecMergeJoin(MergeJoin *node)
|
||||
break;
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* now check the outer skip qual to see if we
|
||||
* should now skip outer tuples... if we fail the
|
||||
* outer skip qual, then we know we have a new pair
|
||||
* of matching tuples.
|
||||
* ----------------
|
||||
/*
|
||||
* now check the outer skip qual to see if we should now
|
||||
* skip outer tuples... if we fail the outer skip qual,
|
||||
* then we know we have a new pair of matching tuples.
|
||||
*/
|
||||
compareResult = MergeCompare(mergeclauses,
|
||||
outerSkipQual,
|
||||
@@ -1232,10 +1206,9 @@ ExecMergeJoin(MergeJoin *node)
|
||||
mergestate->mj_JoinState = EXEC_MJ_JOINMARK;
|
||||
break;
|
||||
|
||||
/*------------------------------------------------
|
||||
/*
|
||||
* Before advancing, we check to see if we must emit an
|
||||
* outer-join fill tuple for this inner tuple.
|
||||
*------------------------------------------------
|
||||
*/
|
||||
case EXEC_MJ_SKIPINNER_ADVANCE:
|
||||
MJ_printf("ExecMergeJoin: EXEC_MJ_SKIPINNER_ADVANCE\n");
|
||||
@@ -1259,10 +1232,11 @@ ExecMergeJoin(MergeJoin *node)
|
||||
|
||||
if (ExecQual(otherqual, econtext, false))
|
||||
{
|
||||
/* ----------------
|
||||
* qualification succeeded. now form the desired
|
||||
* projection tuple and return the slot containing it.
|
||||
* ----------------
|
||||
|
||||
/*
|
||||
* qualification succeeded. now form the desired
|
||||
* projection tuple and return the slot containing
|
||||
* it.
|
||||
*/
|
||||
TupleTableSlot *result;
|
||||
ExprDoneCond isDone;
|
||||
@@ -1281,19 +1255,17 @@ ExecMergeJoin(MergeJoin *node)
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* now we get the next inner tuple, if any
|
||||
* ----------------
|
||||
/*
|
||||
* now we get the next inner tuple, if any
|
||||
*/
|
||||
innerTupleSlot = ExecProcNode(innerPlan, (Plan *) node);
|
||||
mergestate->mj_InnerTupleSlot = innerTupleSlot;
|
||||
MJ_DEBUG_PROC_NODE(innerTupleSlot);
|
||||
mergestate->mj_MatchedInner = false;
|
||||
|
||||
/* ----------------
|
||||
* if the inner tuple is null then we are done with the
|
||||
* join, unless we have outer tuples we need to null-fill.
|
||||
* ----------------
|
||||
/*
|
||||
* if the inner tuple is null then we are done with the
|
||||
* join, unless we have outer tuples we need to null-fill.
|
||||
*/
|
||||
if (TupIsNull(innerTupleSlot))
|
||||
{
|
||||
@@ -1313,9 +1285,8 @@ ExecMergeJoin(MergeJoin *node)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* otherwise test the new tuple against the skip qual.
|
||||
* ----------------
|
||||
/*
|
||||
* otherwise test the new tuple against the skip qual.
|
||||
*/
|
||||
mergestate->mj_JoinState = EXEC_MJ_SKIPINNER_TEST;
|
||||
break;
|
||||
@@ -1349,10 +1320,11 @@ ExecMergeJoin(MergeJoin *node)
|
||||
|
||||
if (ExecQual(otherqual, econtext, false))
|
||||
{
|
||||
/* ----------------
|
||||
* qualification succeeded. now form the desired
|
||||
* projection tuple and return the slot containing it.
|
||||
* ----------------
|
||||
|
||||
/*
|
||||
* qualification succeeded. now form the desired
|
||||
* projection tuple and return the slot containing
|
||||
* it.
|
||||
*/
|
||||
TupleTableSlot *result;
|
||||
ExprDoneCond isDone;
|
||||
@@ -1371,9 +1343,8 @@ ExecMergeJoin(MergeJoin *node)
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* now we get the next inner tuple, if any
|
||||
* ----------------
|
||||
/*
|
||||
* now we get the next inner tuple, if any
|
||||
*/
|
||||
innerTupleSlot = ExecProcNode(innerPlan, (Plan *) node);
|
||||
mergestate->mj_InnerTupleSlot = innerTupleSlot;
|
||||
@@ -1418,10 +1389,11 @@ ExecMergeJoin(MergeJoin *node)
|
||||
|
||||
if (ExecQual(otherqual, econtext, false))
|
||||
{
|
||||
/* ----------------
|
||||
* qualification succeeded. now form the desired
|
||||
* projection tuple and return the slot containing it.
|
||||
* ----------------
|
||||
|
||||
/*
|
||||
* qualification succeeded. now form the desired
|
||||
* projection tuple and return the slot containing
|
||||
* it.
|
||||
*/
|
||||
TupleTableSlot *result;
|
||||
ExprDoneCond isDone;
|
||||
@@ -1440,9 +1412,8 @@ ExecMergeJoin(MergeJoin *node)
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* now we get the next outer tuple, if any
|
||||
* ----------------
|
||||
/*
|
||||
* now we get the next outer tuple, if any
|
||||
*/
|
||||
outerTupleSlot = ExecProcNode(outerPlan, (Plan *) node);
|
||||
mergestate->mj_OuterTupleSlot = outerTupleSlot;
|
||||
@@ -1487,39 +1458,35 @@ ExecInitMergeJoin(MergeJoin *node, EState *estate, Plan *parent)
|
||||
MJ1_printf("ExecInitMergeJoin: %s\n",
|
||||
"initializing node");
|
||||
|
||||
/* ----------------
|
||||
* assign the node's execution state and
|
||||
* get the range table and direction from it
|
||||
* ----------------
|
||||
/*
|
||||
* assign the node's execution state and get the range table and
|
||||
* direction from it
|
||||
*/
|
||||
node->join.plan.state = estate;
|
||||
|
||||
/* ----------------
|
||||
* create new merge state for node
|
||||
* ----------------
|
||||
/*
|
||||
* create new merge state for node
|
||||
*/
|
||||
mergestate = makeNode(MergeJoinState);
|
||||
node->mergestate = mergestate;
|
||||
|
||||
/* ----------------
|
||||
* Miscellaneous initialization
|
||||
/*
|
||||
* Miscellaneous initialization
|
||||
*
|
||||
* + create expression context for node
|
||||
* ----------------
|
||||
* create expression context for node
|
||||
*/
|
||||
ExecAssignExprContext(estate, &mergestate->jstate);
|
||||
|
||||
/* ----------------
|
||||
* initialize subplans
|
||||
* ----------------
|
||||
/*
|
||||
* initialize subplans
|
||||
*/
|
||||
ExecInitNode(outerPlan((Plan *) node), estate, (Plan *) node);
|
||||
ExecInitNode(innerPlan((Plan *) node), estate, (Plan *) node);
|
||||
|
||||
#define MERGEJOIN_NSLOTS 4
|
||||
/* ----------------
|
||||
* tuple table initialization
|
||||
* ----------------
|
||||
|
||||
/*
|
||||
* tuple table initialization
|
||||
*/
|
||||
ExecInitResultTupleSlot(estate, &mergestate->jstate);
|
||||
|
||||
@@ -1569,16 +1536,14 @@ ExecInitMergeJoin(MergeJoin *node, EState *estate, Plan *parent)
|
||||
(int) node->join.jointype);
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* initialize tuple type and projection info
|
||||
* ----------------
|
||||
/*
|
||||
* initialize tuple type and projection info
|
||||
*/
|
||||
ExecAssignResultTypeFromTL((Plan *) node, &mergestate->jstate);
|
||||
ExecAssignProjectionInfo((Plan *) node, &mergestate->jstate);
|
||||
|
||||
/* ----------------
|
||||
* form merge skip qualifications
|
||||
* ----------------
|
||||
/*
|
||||
* form merge skip qualifications
|
||||
*/
|
||||
joinclauses = node->mergeclauses;
|
||||
mergestate->mj_OuterSkipQual = MJFormSkipQual(joinclauses, "<");
|
||||
@@ -1590,9 +1555,8 @@ ExecInitMergeJoin(MergeJoin *node, EState *estate, Plan *parent)
|
||||
MJ_nodeDisplay(mergestate->mj_InnerSkipQual);
|
||||
MJ_printf("\n");
|
||||
|
||||
/* ----------------
|
||||
* initialize join state
|
||||
* ----------------
|
||||
/*
|
||||
* initialize join state
|
||||
*/
|
||||
mergestate->mj_JoinState = EXEC_MJ_INITIALIZE;
|
||||
mergestate->jstate.cs_TupFromTlist = false;
|
||||
@@ -1601,9 +1565,8 @@ ExecInitMergeJoin(MergeJoin *node, EState *estate, Plan *parent)
|
||||
mergestate->mj_OuterTupleSlot = NULL;
|
||||
mergestate->mj_InnerTupleSlot = NULL;
|
||||
|
||||
/* ----------------
|
||||
* initialization successful
|
||||
* ----------------
|
||||
/*
|
||||
* initialization successful
|
||||
*/
|
||||
MJ1_printf("ExecInitMergeJoin: %s\n",
|
||||
"node initialized");
|
||||
@@ -1634,34 +1597,29 @@ ExecEndMergeJoin(MergeJoin *node)
|
||||
MJ1_printf("ExecEndMergeJoin: %s\n",
|
||||
"ending node processing");
|
||||
|
||||
/* ----------------
|
||||
* get state information from the node
|
||||
* ----------------
|
||||
/*
|
||||
* get state information from the node
|
||||
*/
|
||||
mergestate = node->mergestate;
|
||||
|
||||
/* ----------------
|
||||
* Free the projection info and the scan attribute info
|
||||
/*
|
||||
* Free the projection info and the scan attribute info
|
||||
*
|
||||
* Note: we don't ExecFreeResultType(mergestate)
|
||||
* because the rule manager depends on the tupType
|
||||
* returned by ExecMain(). So for now, this
|
||||
* is freed at end-transaction time. -cim 6/2/91
|
||||
* ----------------
|
||||
* Note: we don't ExecFreeResultType(mergestate) because the rule manager
|
||||
* depends on the tupType returned by ExecMain(). So for now, this is
|
||||
* freed at end-transaction time. -cim 6/2/91
|
||||
*/
|
||||
ExecFreeProjectionInfo(&mergestate->jstate);
|
||||
ExecFreeExprContext(&mergestate->jstate);
|
||||
|
||||
/* ----------------
|
||||
* shut down the subplans
|
||||
* ----------------
|
||||
/*
|
||||
* shut down the subplans
|
||||
*/
|
||||
ExecEndNode((Plan *) innerPlan((Plan *) node), (Plan *) node);
|
||||
ExecEndNode((Plan *) outerPlan((Plan *) node), (Plan *) node);
|
||||
|
||||
/* ----------------
|
||||
* clean out the tuple table
|
||||
* ----------------
|
||||
/*
|
||||
* clean out the tuple table
|
||||
*/
|
||||
ExecClearTuple(mergestate->jstate.cs_ResultTupleSlot);
|
||||
ExecClearTuple(mergestate->mj_MarkedTupleSlot);
|
||||
|
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/nodeNestloop.c,v 1.23 2001/03/22 03:59:29 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/nodeNestloop.c,v 1.24 2001/03/22 06:16:13 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -68,9 +68,8 @@ ExecNestLoop(NestLoop *node)
|
||||
List *otherqual;
|
||||
ExprContext *econtext;
|
||||
|
||||
/* ----------------
|
||||
* get information from the node
|
||||
* ----------------
|
||||
/*
|
||||
* get information from the node
|
||||
*/
|
||||
ENL1_printf("getting info from node");
|
||||
|
||||
@@ -81,18 +80,16 @@ ExecNestLoop(NestLoop *node)
|
||||
innerPlan = innerPlan((Plan *) node);
|
||||
econtext = nlstate->jstate.cs_ExprContext;
|
||||
|
||||
/* ----------------
|
||||
/*
|
||||
* get the current outer tuple
|
||||
* ----------------
|
||||
*/
|
||||
outerTupleSlot = nlstate->jstate.cs_OuterTupleSlot;
|
||||
econtext->ecxt_outertuple = outerTupleSlot;
|
||||
|
||||
/* ----------------
|
||||
* Check to see if we're still projecting out tuples from a previous
|
||||
* join tuple (because there is a function-returning-set in the
|
||||
* projection expressions). If so, try to project another one.
|
||||
* ----------------
|
||||
/*
|
||||
* Check to see if we're still projecting out tuples from a previous
|
||||
* join tuple (because there is a function-returning-set in the
|
||||
* projection expressions). If so, try to project another one.
|
||||
*/
|
||||
if (nlstate->jstate.cs_TupFromTlist)
|
||||
{
|
||||
@@ -106,37 +103,34 @@ ExecNestLoop(NestLoop *node)
|
||||
nlstate->jstate.cs_TupFromTlist = false;
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* Reset per-tuple memory context to free any expression evaluation
|
||||
* storage allocated in the previous tuple cycle. Note this can't
|
||||
* happen until we're done projecting out tuples from a join tuple.
|
||||
* ----------------
|
||||
/*
|
||||
* Reset per-tuple memory context to free any expression evaluation
|
||||
* storage allocated in the previous tuple cycle. Note this can't
|
||||
* happen until we're done projecting out tuples from a join tuple.
|
||||
*/
|
||||
ResetExprContext(econtext);
|
||||
|
||||
/* ----------------
|
||||
* Ok, everything is setup for the join so now loop until
|
||||
* we return a qualifying join tuple.
|
||||
* ----------------
|
||||
/*
|
||||
* Ok, everything is setup for the join so now loop until we return a
|
||||
* qualifying join tuple.
|
||||
*/
|
||||
ENL1_printf("entering main loop");
|
||||
|
||||
for (;;)
|
||||
{
|
||||
/* ----------------
|
||||
* If we don't have an outer tuple, get the next one and
|
||||
* reset the inner scan.
|
||||
* ----------------
|
||||
|
||||
/*
|
||||
* If we don't have an outer tuple, get the next one and reset the
|
||||
* inner scan.
|
||||
*/
|
||||
if (nlstate->nl_NeedNewOuter)
|
||||
{
|
||||
ENL1_printf("getting new outer tuple");
|
||||
outerTupleSlot = ExecProcNode(outerPlan, (Plan *) node);
|
||||
|
||||
/* ----------------
|
||||
* if there are no more outer tuples, then the join
|
||||
* is complete..
|
||||
* ----------------
|
||||
/*
|
||||
* if there are no more outer tuples, then the join is
|
||||
* complete..
|
||||
*/
|
||||
if (TupIsNull(outerTupleSlot))
|
||||
{
|
||||
@@ -150,9 +144,8 @@ ExecNestLoop(NestLoop *node)
|
||||
nlstate->nl_NeedNewOuter = false;
|
||||
nlstate->nl_MatchedOuter = false;
|
||||
|
||||
/* ----------------
|
||||
* now rescan the inner plan
|
||||
* ----------------
|
||||
/*
|
||||
* now rescan the inner plan
|
||||
*/
|
||||
ENL1_printf("rescanning inner plan");
|
||||
|
||||
@@ -164,9 +157,8 @@ ExecNestLoop(NestLoop *node)
|
||||
ExecReScan(innerPlan, econtext, (Plan *) node);
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* we have an outerTuple, try to get the next inner tuple.
|
||||
* ----------------
|
||||
/*
|
||||
* we have an outerTuple, try to get the next inner tuple.
|
||||
*/
|
||||
ENL1_printf("getting new inner tuple");
|
||||
|
||||
@@ -195,11 +187,11 @@ ExecNestLoop(NestLoop *node)
|
||||
|
||||
if (ExecQual(otherqual, econtext, false))
|
||||
{
|
||||
/* ----------------
|
||||
* qualification was satisfied so we project and
|
||||
* return the slot containing the result tuple
|
||||
* using ExecProject().
|
||||
* ----------------
|
||||
|
||||
/*
|
||||
* qualification was satisfied so we project and
|
||||
* return the slot containing the result tuple using
|
||||
* ExecProject().
|
||||
*/
|
||||
TupleTableSlot *result;
|
||||
ExprDoneCond isDone;
|
||||
@@ -223,14 +215,13 @@ ExecNestLoop(NestLoop *node)
|
||||
continue;
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* at this point we have a new pair of inner and outer
|
||||
* tuples so we test the inner and outer tuples to see
|
||||
* if they satisfy the node's qualification.
|
||||
/*
|
||||
* at this point we have a new pair of inner and outer tuples so
|
||||
* we test the inner and outer tuples to see if they satisfy the
|
||||
* node's qualification.
|
||||
*
|
||||
* Only the joinquals determine MatchedOuter status,
|
||||
* but all quals must pass to actually return the tuple.
|
||||
* ----------------
|
||||
* Only the joinquals determine MatchedOuter status, but all quals
|
||||
* must pass to actually return the tuple.
|
||||
*/
|
||||
ENL1_printf("testing qualification");
|
||||
|
||||
@@ -240,11 +231,11 @@ ExecNestLoop(NestLoop *node)
|
||||
|
||||
if (otherqual == NIL || ExecQual(otherqual, econtext, false))
|
||||
{
|
||||
/* ----------------
|
||||
* qualification was satisfied so we project and
|
||||
* return the slot containing the result tuple
|
||||
* using ExecProject().
|
||||
* ----------------
|
||||
|
||||
/*
|
||||
* qualification was satisfied so we project and return
|
||||
* the slot containing the result tuple using
|
||||
* ExecProject().
|
||||
*/
|
||||
TupleTableSlot *result;
|
||||
ExprDoneCond isDone;
|
||||
@@ -262,9 +253,8 @@ ExecNestLoop(NestLoop *node)
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* Tuple fails qual, so free per-tuple memory and try again.
|
||||
* ----------------
|
||||
/*
|
||||
* Tuple fails qual, so free per-tuple memory and try again.
|
||||
*/
|
||||
ResetExprContext(econtext);
|
||||
|
||||
@@ -288,38 +278,34 @@ ExecInitNestLoop(NestLoop *node, EState *estate, Plan *parent)
|
||||
NL1_printf("ExecInitNestLoop: %s\n",
|
||||
"initializing node");
|
||||
|
||||
/* ----------------
|
||||
* assign execution state to node
|
||||
* ----------------
|
||||
/*
|
||||
* assign execution state to node
|
||||
*/
|
||||
node->join.plan.state = estate;
|
||||
|
||||
/* ----------------
|
||||
* create new nest loop state
|
||||
* ----------------
|
||||
/*
|
||||
* create new nest loop state
|
||||
*/
|
||||
nlstate = makeNode(NestLoopState);
|
||||
node->nlstate = nlstate;
|
||||
|
||||
/* ----------------
|
||||
* Miscellaneous initialization
|
||||
/*
|
||||
* Miscellaneous initialization
|
||||
*
|
||||
* + create expression context for node
|
||||
* ----------------
|
||||
* create expression context for node
|
||||
*/
|
||||
ExecAssignExprContext(estate, &nlstate->jstate);
|
||||
|
||||
/* ----------------
|
||||
* now initialize children
|
||||
* ----------------
|
||||
/*
|
||||
* now initialize children
|
||||
*/
|
||||
ExecInitNode(outerPlan((Plan *) node), estate, (Plan *) node);
|
||||
ExecInitNode(innerPlan((Plan *) node), estate, (Plan *) node);
|
||||
|
||||
#define NESTLOOP_NSLOTS 2
|
||||
/* ----------------
|
||||
* tuple table initialization
|
||||
* ----------------
|
||||
|
||||
/*
|
||||
* tuple table initialization
|
||||
*/
|
||||
ExecInitResultTupleSlot(estate, &nlstate->jstate);
|
||||
|
||||
@@ -337,16 +323,14 @@ ExecInitNestLoop(NestLoop *node, EState *estate, Plan *parent)
|
||||
(int) node->join.jointype);
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* initialize tuple type and projection info
|
||||
* ----------------
|
||||
/*
|
||||
* initialize tuple type and projection info
|
||||
*/
|
||||
ExecAssignResultTypeFromTL((Plan *) node, &nlstate->jstate);
|
||||
ExecAssignProjectionInfo((Plan *) node, &nlstate->jstate);
|
||||
|
||||
/* ----------------
|
||||
* finally, wipe the current outer tuple clean.
|
||||
* ----------------
|
||||
/*
|
||||
* finally, wipe the current outer tuple clean.
|
||||
*/
|
||||
nlstate->jstate.cs_OuterTupleSlot = NULL;
|
||||
nlstate->jstate.cs_TupFromTlist = false;
|
||||
@@ -380,34 +364,29 @@ ExecEndNestLoop(NestLoop *node)
|
||||
NL1_printf("ExecEndNestLoop: %s\n",
|
||||
"ending node processing");
|
||||
|
||||
/* ----------------
|
||||
* get info from the node
|
||||
* ----------------
|
||||
/*
|
||||
* get info from the node
|
||||
*/
|
||||
nlstate = node->nlstate;
|
||||
|
||||
/* ----------------
|
||||
* Free the projection info
|
||||
/*
|
||||
* Free the projection info
|
||||
*
|
||||
* Note: we don't ExecFreeResultType(nlstate)
|
||||
* because the rule manager depends on the tupType
|
||||
* returned by ExecMain(). So for now, this
|
||||
* is freed at end-transaction time. -cim 6/2/91
|
||||
* ----------------
|
||||
* Note: we don't ExecFreeResultType(nlstate) because the rule manager
|
||||
* depends on the tupType returned by ExecMain(). So for now, this is
|
||||
* freed at end-transaction time. -cim 6/2/91
|
||||
*/
|
||||
ExecFreeProjectionInfo(&nlstate->jstate);
|
||||
ExecFreeExprContext(&nlstate->jstate);
|
||||
|
||||
/* ----------------
|
||||
* close down subplans
|
||||
* ----------------
|
||||
/*
|
||||
* close down subplans
|
||||
*/
|
||||
ExecEndNode(outerPlan((Plan *) node), (Plan *) node);
|
||||
ExecEndNode(innerPlan((Plan *) node), (Plan *) node);
|
||||
|
||||
/* ----------------
|
||||
* clean out the tuple table
|
||||
* ----------------
|
||||
/*
|
||||
* clean out the tuple table
|
||||
*/
|
||||
ExecClearTuple(nlstate->jstate.cs_ResultTupleSlot);
|
||||
|
||||
|
@@ -34,7 +34,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/nodeResult.c,v 1.18 2001/03/22 03:59:29 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/nodeResult.c,v 1.19 2001/03/22 06:16:13 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -69,16 +69,14 @@ ExecResult(Result *node)
|
||||
ExprContext *econtext;
|
||||
ExprDoneCond isDone;
|
||||
|
||||
/* ----------------
|
||||
* initialize the result node's state
|
||||
* ----------------
|
||||
/*
|
||||
* initialize the result node's state
|
||||
*/
|
||||
resstate = node->resstate;
|
||||
econtext = resstate->cstate.cs_ExprContext;
|
||||
|
||||
/* ----------------
|
||||
* check constant qualifications like (2 > 1), if not already done
|
||||
* ----------------
|
||||
/*
|
||||
* check constant qualifications like (2 > 1), if not already done
|
||||
*/
|
||||
if (resstate->rs_checkqual)
|
||||
{
|
||||
@@ -94,11 +92,10 @@ ExecResult(Result *node)
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* Check to see if we're still projecting out tuples from a previous
|
||||
* scan tuple (because there is a function-returning-set in the
|
||||
* projection expressions). If so, try to project another one.
|
||||
* ----------------
|
||||
/*
|
||||
* Check to see if we're still projecting out tuples from a previous
|
||||
* scan tuple (because there is a function-returning-set in the
|
||||
* projection expressions). If so, try to project another one.
|
||||
*/
|
||||
if (resstate->cstate.cs_TupFromTlist)
|
||||
{
|
||||
@@ -109,20 +106,18 @@ ExecResult(Result *node)
|
||||
resstate->cstate.cs_TupFromTlist = false;
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* Reset per-tuple memory context to free any expression evaluation
|
||||
* storage allocated in the previous tuple cycle. Note this can't
|
||||
* happen until we're done projecting out tuples from a scan tuple.
|
||||
* ----------------
|
||||
/*
|
||||
* Reset per-tuple memory context to free any expression evaluation
|
||||
* storage allocated in the previous tuple cycle. Note this can't
|
||||
* happen until we're done projecting out tuples from a scan tuple.
|
||||
*/
|
||||
ResetExprContext(econtext);
|
||||
|
||||
/* ----------------
|
||||
* if rs_done is true then it means that we were asked to return
|
||||
* a constant tuple and we already did the last time ExecResult()
|
||||
* was called, OR that we failed the constant qual check.
|
||||
* Either way, now we are through.
|
||||
* ----------------
|
||||
/*
|
||||
* if rs_done is true then it means that we were asked to return a
|
||||
* constant tuple and we already did the last time ExecResult() was
|
||||
* called, OR that we failed the constant qual check. Either way, now
|
||||
* we are through.
|
||||
*/
|
||||
while (!resstate->rs_done)
|
||||
{
|
||||
@@ -130,9 +125,10 @@ ExecResult(Result *node)
|
||||
|
||||
if (outerPlan != NULL)
|
||||
{
|
||||
/* ----------------
|
||||
* retrieve tuples from the outer plan until there are no more.
|
||||
* ----------------
|
||||
|
||||
/*
|
||||
* retrieve tuples from the outer plan until there are no
|
||||
* more.
|
||||
*/
|
||||
outerTupleSlot = ExecProcNode(outerPlan, (Plan *) node);
|
||||
|
||||
@@ -141,28 +137,27 @@ ExecResult(Result *node)
|
||||
|
||||
resstate->cstate.cs_OuterTupleSlot = outerTupleSlot;
|
||||
|
||||
/* ----------------
|
||||
* XXX gross hack. use outer tuple as scan tuple for projection
|
||||
* ----------------
|
||||
/*
|
||||
* XXX gross hack. use outer tuple as scan tuple for
|
||||
* projection
|
||||
*/
|
||||
econtext->ecxt_outertuple = outerTupleSlot;
|
||||
econtext->ecxt_scantuple = outerTupleSlot;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* ----------------
|
||||
* if we don't have an outer plan, then we are just generating
|
||||
* the results from a constant target list. Do it only once.
|
||||
* ----------------
|
||||
|
||||
/*
|
||||
* if we don't have an outer plan, then we are just generating
|
||||
* the results from a constant target list. Do it only once.
|
||||
*/
|
||||
resstate->rs_done = true;
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* form the result tuple using ExecProject(), and return it
|
||||
* --- unless the projection produces an empty set, in which case
|
||||
* we must loop back to see if there are more outerPlan tuples.
|
||||
* ----------------
|
||||
/*
|
||||
* form the result tuple using ExecProject(), and return it ---
|
||||
* unless the projection produces an empty set, in which case we
|
||||
* must loop back to see if there are more outerPlan tuples.
|
||||
*/
|
||||
resultSlot = ExecProject(resstate->cstate.cs_ProjInfo, &isDone);
|
||||
|
||||
@@ -189,39 +184,35 @@ ExecInitResult(Result *node, EState *estate, Plan *parent)
|
||||
{
|
||||
ResultState *resstate;
|
||||
|
||||
/* ----------------
|
||||
* assign execution state to node
|
||||
* ----------------
|
||||
/*
|
||||
* assign execution state to node
|
||||
*/
|
||||
node->plan.state = estate;
|
||||
|
||||
/* ----------------
|
||||
* create new ResultState for node
|
||||
* ----------------
|
||||
/*
|
||||
* create new ResultState for node
|
||||
*/
|
||||
resstate = makeNode(ResultState);
|
||||
resstate->rs_done = false;
|
||||
resstate->rs_checkqual = (node->resconstantqual == NULL) ? false : true;
|
||||
node->resstate = resstate;
|
||||
|
||||
/* ----------------
|
||||
* Miscellaneous initialization
|
||||
/*
|
||||
* Miscellaneous initialization
|
||||
*
|
||||
* + create expression context for node
|
||||
* ----------------
|
||||
* create expression context for node
|
||||
*/
|
||||
ExecAssignExprContext(estate, &resstate->cstate);
|
||||
|
||||
#define RESULT_NSLOTS 1
|
||||
/* ----------------
|
||||
* tuple table initialization
|
||||
* ----------------
|
||||
|
||||
/*
|
||||
* tuple table initialization
|
||||
*/
|
||||
ExecInitResultTupleSlot(estate, &resstate->cstate);
|
||||
|
||||
/* ----------------
|
||||
* then initialize children
|
||||
* ----------------
|
||||
/*
|
||||
* then initialize children
|
||||
*/
|
||||
ExecInitNode(outerPlan(node), estate, (Plan *) node);
|
||||
|
||||
@@ -230,9 +221,8 @@ ExecInitResult(Result *node, EState *estate, Plan *parent)
|
||||
*/
|
||||
Assert(innerPlan(node) == NULL);
|
||||
|
||||
/* ----------------
|
||||
* initialize tuple type and projection info
|
||||
* ----------------
|
||||
/*
|
||||
* initialize tuple type and projection info
|
||||
*/
|
||||
ExecAssignResultTypeFromTL((Plan *) node, &resstate->cstate);
|
||||
ExecAssignProjectionInfo((Plan *) node, &resstate->cstate);
|
||||
@@ -259,27 +249,23 @@ ExecEndResult(Result *node)
|
||||
|
||||
resstate = node->resstate;
|
||||
|
||||
/* ----------------
|
||||
* Free the projection info
|
||||
/*
|
||||
* Free the projection info
|
||||
*
|
||||
* Note: we don't ExecFreeResultType(resstate)
|
||||
* because the rule manager depends on the tupType
|
||||
* returned by ExecMain(). So for now, this
|
||||
* is freed at end-transaction time. -cim 6/2/91
|
||||
* ----------------
|
||||
* Note: we don't ExecFreeResultType(resstate) because the rule manager
|
||||
* depends on the tupType returned by ExecMain(). So for now, this is
|
||||
* freed at end-transaction time. -cim 6/2/91
|
||||
*/
|
||||
ExecFreeProjectionInfo(&resstate->cstate);
|
||||
ExecFreeExprContext(&resstate->cstate);
|
||||
|
||||
/* ----------------
|
||||
* shut down subplans
|
||||
* ----------------
|
||||
/*
|
||||
* shut down subplans
|
||||
*/
|
||||
ExecEndNode(outerPlan(node), (Plan *) node);
|
||||
|
||||
/* ----------------
|
||||
* clean out the tuple table
|
||||
* ----------------
|
||||
/*
|
||||
* clean out the tuple table
|
||||
*/
|
||||
ExecClearTuple(resstate->cstate.cs_ResultTupleSlot);
|
||||
pfree(resstate);
|
||||
|
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/nodeSeqscan.c,v 1.28 2001/03/22 03:59:29 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/nodeSeqscan.c,v 1.29 2001/03/22 06:16:13 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -54,9 +54,8 @@ SeqNext(SeqScan *node)
|
||||
ScanDirection direction;
|
||||
TupleTableSlot *slot;
|
||||
|
||||
/* ----------------
|
||||
* get information from the estate and scan state
|
||||
* ----------------
|
||||
/*
|
||||
* get information from the estate and scan state
|
||||
*/
|
||||
estate = node->plan.state;
|
||||
scanstate = node->scanstate;
|
||||
@@ -91,21 +90,19 @@ SeqNext(SeqScan *node)
|
||||
return (slot);
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* get the next tuple from the access methods
|
||||
* ----------------
|
||||
/*
|
||||
* get the next tuple from the access methods
|
||||
*/
|
||||
tuple = heap_getnext(scandesc, ScanDirectionIsBackward(direction));
|
||||
|
||||
/* ----------------
|
||||
* save the tuple and the buffer returned to us by the access methods
|
||||
* in our scan tuple slot and return the slot. Note: we pass 'false'
|
||||
* because tuples returned by heap_getnext() are pointers onto
|
||||
* disk pages and were not created with palloc() and so should not
|
||||
* be pfree()'d. Note also that ExecStoreTuple will increment the
|
||||
* refcount of the buffer; the refcount will not be dropped until
|
||||
* the tuple table slot is cleared.
|
||||
* ----------------
|
||||
/*
|
||||
* save the tuple and the buffer returned to us by the access methods
|
||||
* in our scan tuple slot and return the slot. Note: we pass 'false'
|
||||
* because tuples returned by heap_getnext() are pointers onto disk
|
||||
* pages and were not created with palloc() and so should not be
|
||||
* pfree()'d. Note also that ExecStoreTuple will increment the
|
||||
* refcount of the buffer; the refcount will not be dropped until the
|
||||
* tuple table slot is cleared.
|
||||
*/
|
||||
|
||||
slot = ExecStoreTuple(tuple,/* tuple to store */
|
||||
@@ -130,9 +127,9 @@ SeqNext(SeqScan *node)
|
||||
TupleTableSlot *
|
||||
ExecSeqScan(SeqScan *node)
|
||||
{
|
||||
/* ----------------
|
||||
* use SeqNext as access method
|
||||
* ----------------
|
||||
|
||||
/*
|
||||
* use SeqNext as access method
|
||||
*/
|
||||
return ExecScan(node, (ExecScanAccessMtd) SeqNext);
|
||||
}
|
||||
@@ -156,11 +153,9 @@ InitScanRelation(SeqScan *node, EState *estate,
|
||||
Relation currentRelation;
|
||||
HeapScanDesc currentScanDesc;
|
||||
|
||||
/* ----------------
|
||||
* get the relation object id from the relid'th entry
|
||||
* in the range table, open that relation and initialize
|
||||
* the scan state...
|
||||
* ----------------
|
||||
/*
|
||||
* get the relation object id from the relid'th entry in the range
|
||||
* table, open that relation and initialize the scan state...
|
||||
*/
|
||||
relid = node->scanrelid;
|
||||
rangeTable = estate->es_range_table;
|
||||
@@ -197,55 +192,49 @@ ExecInitSeqScan(SeqScan *node, EState *estate, Plan *parent)
|
||||
Oid reloid;
|
||||
HeapScanDesc scandesc;
|
||||
|
||||
/* ----------------
|
||||
* Once upon a time it was possible to have an outerPlan of a SeqScan,
|
||||
* but not any more.
|
||||
* ----------------
|
||||
/*
|
||||
* Once upon a time it was possible to have an outerPlan of a SeqScan,
|
||||
* but not any more.
|
||||
*/
|
||||
Assert(outerPlan((Plan *) node) == NULL);
|
||||
Assert(innerPlan((Plan *) node) == NULL);
|
||||
|
||||
/* ----------------
|
||||
* assign the node's execution state
|
||||
* ----------------
|
||||
/*
|
||||
* assign the node's execution state
|
||||
*/
|
||||
node->plan.state = estate;
|
||||
|
||||
/* ----------------
|
||||
* create new CommonScanState for node
|
||||
* ----------------
|
||||
/*
|
||||
* create new CommonScanState for node
|
||||
*/
|
||||
scanstate = makeNode(CommonScanState);
|
||||
node->scanstate = scanstate;
|
||||
|
||||
/* ----------------
|
||||
* Miscellaneous initialization
|
||||
/*
|
||||
* Miscellaneous initialization
|
||||
*
|
||||
* + create expression context for node
|
||||
* ----------------
|
||||
* create expression context for node
|
||||
*/
|
||||
ExecAssignExprContext(estate, &scanstate->cstate);
|
||||
|
||||
#define SEQSCAN_NSLOTS 3
|
||||
/* ----------------
|
||||
* tuple table initialization
|
||||
* ----------------
|
||||
|
||||
/*
|
||||
* tuple table initialization
|
||||
*/
|
||||
ExecInitResultTupleSlot(estate, &scanstate->cstate);
|
||||
ExecInitScanTupleSlot(estate, scanstate);
|
||||
|
||||
/* ----------------
|
||||
* initialize scan relation
|
||||
* ----------------
|
||||
/*
|
||||
* initialize scan relation
|
||||
*/
|
||||
reloid = InitScanRelation(node, estate, scanstate);
|
||||
|
||||
scandesc = scanstate->css_currentScanDesc;
|
||||
scanstate->cstate.cs_TupFromTlist = false;
|
||||
|
||||
/* ----------------
|
||||
* initialize tuple type
|
||||
* ----------------
|
||||
/*
|
||||
* initialize tuple type
|
||||
*/
|
||||
ExecAssignResultTypeFromTL((Plan *) node, &scanstate->cstate);
|
||||
ExecAssignProjectionInfo((Plan *) node, &scanstate->cstate);
|
||||
@@ -272,33 +261,28 @@ ExecEndSeqScan(SeqScan *node)
|
||||
{
|
||||
CommonScanState *scanstate;
|
||||
|
||||
/* ----------------
|
||||
* get information from node
|
||||
* ----------------
|
||||
/*
|
||||
* get information from node
|
||||
*/
|
||||
scanstate = node->scanstate;
|
||||
|
||||
/* ----------------
|
||||
* Free the projection info and the scan attribute info
|
||||
/*
|
||||
* Free the projection info and the scan attribute info
|
||||
*
|
||||
* Note: we don't ExecFreeResultType(scanstate)
|
||||
* because the rule manager depends on the tupType
|
||||
* returned by ExecMain(). So for now, this
|
||||
* is freed at end-transaction time. -cim 6/2/91
|
||||
* ----------------
|
||||
* Note: we don't ExecFreeResultType(scanstate) because the rule manager
|
||||
* depends on the tupType returned by ExecMain(). So for now, this is
|
||||
* freed at end-transaction time. -cim 6/2/91
|
||||
*/
|
||||
ExecFreeProjectionInfo(&scanstate->cstate);
|
||||
ExecFreeExprContext(&scanstate->cstate);
|
||||
|
||||
/* ----------------
|
||||
/*
|
||||
* close scan relation
|
||||
* ----------------
|
||||
*/
|
||||
ExecCloseR((Plan *) node);
|
||||
|
||||
/* ----------------
|
||||
* clean out the tuple table
|
||||
* ----------------
|
||||
/*
|
||||
* clean out the tuple table
|
||||
*/
|
||||
ExecClearTuple(scanstate->cstate.cs_ResultTupleSlot);
|
||||
ExecClearTuple(scanstate->css_ScanTupleSlot);
|
||||
|
@@ -21,7 +21,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/nodeSetOp.c,v 1.3 2001/03/22 03:59:29 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/nodeSetOp.c,v 1.4 2001/03/22 06:16:13 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -51,19 +51,17 @@ ExecSetOp(SetOp *node)
|
||||
Plan *outerPlan;
|
||||
TupleDesc tupDesc;
|
||||
|
||||
/* ----------------
|
||||
* get information from the node
|
||||
* ----------------
|
||||
/*
|
||||
* get information from the node
|
||||
*/
|
||||
setopstate = node->setopstate;
|
||||
outerPlan = outerPlan((Plan *) node);
|
||||
resultTupleSlot = setopstate->cstate.cs_ResultTupleSlot;
|
||||
tupDesc = ExecGetResultType(&setopstate->cstate);
|
||||
|
||||
/* ----------------
|
||||
* If the previously-returned tuple needs to be returned more than
|
||||
* once, keep returning it.
|
||||
* ----------------
|
||||
/*
|
||||
* If the previously-returned tuple needs to be returned more than
|
||||
* once, keep returning it.
|
||||
*/
|
||||
if (setopstate->numOutput > 0)
|
||||
{
|
||||
@@ -74,23 +72,21 @@ ExecSetOp(SetOp *node)
|
||||
/* Flag that we have no current tuple */
|
||||
ExecClearTuple(resultTupleSlot);
|
||||
|
||||
/* ----------------
|
||||
* Absorb groups of duplicate tuples, counting them, and
|
||||
* saving the first of each group as a possible return value.
|
||||
* At the end of each group, decide whether to return anything.
|
||||
/*
|
||||
* Absorb groups of duplicate tuples, counting them, and saving the
|
||||
* first of each group as a possible return value. At the end of each
|
||||
* group, decide whether to return anything.
|
||||
*
|
||||
* We assume that the tuples arrive in sorted order
|
||||
* so we can detect duplicates easily.
|
||||
* ----------------
|
||||
* We assume that the tuples arrive in sorted order so we can detect
|
||||
* duplicates easily.
|
||||
*/
|
||||
for (;;)
|
||||
{
|
||||
TupleTableSlot *inputTupleSlot;
|
||||
bool endOfGroup;
|
||||
|
||||
/* ----------------
|
||||
* fetch a tuple from the outer subplan, unless we already did.
|
||||
* ----------------
|
||||
/*
|
||||
* fetch a tuple from the outer subplan, unless we already did.
|
||||
*/
|
||||
if (setopstate->cstate.cs_OuterTupleSlot == NULL &&
|
||||
!setopstate->subplan_done)
|
||||
@@ -235,15 +231,13 @@ ExecInitSetOp(SetOp *node, EState *estate, Plan *parent)
|
||||
SetOpState *setopstate;
|
||||
Plan *outerPlan;
|
||||
|
||||
/* ----------------
|
||||
* assign execution state to node
|
||||
* ----------------
|
||||
/*
|
||||
* assign execution state to node
|
||||
*/
|
||||
node->plan.state = estate;
|
||||
|
||||
/* ----------------
|
||||
* create new SetOpState for node
|
||||
* ----------------
|
||||
/*
|
||||
* create new SetOpState for node
|
||||
*/
|
||||
setopstate = makeNode(SetOpState);
|
||||
node->setopstate = setopstate;
|
||||
@@ -251,13 +245,12 @@ ExecInitSetOp(SetOp *node, EState *estate, Plan *parent)
|
||||
setopstate->subplan_done = false;
|
||||
setopstate->numOutput = 0;
|
||||
|
||||
/* ----------------
|
||||
* Miscellaneous initialization
|
||||
/*
|
||||
* Miscellaneous initialization
|
||||
*
|
||||
* SetOp nodes have no ExprContext initialization because
|
||||
* they never call ExecQual or ExecProject. But they do need a
|
||||
* per-tuple memory context anyway for calling execTuplesMatch.
|
||||
* ----------------
|
||||
* SetOp nodes have no ExprContext initialization because they never call
|
||||
* ExecQual or ExecProject. But they do need a per-tuple memory
|
||||
* context anyway for calling execTuplesMatch.
|
||||
*/
|
||||
setopstate->tempContext =
|
||||
AllocSetContextCreate(CurrentMemoryContext,
|
||||
@@ -267,23 +260,21 @@ ExecInitSetOp(SetOp *node, EState *estate, Plan *parent)
|
||||
ALLOCSET_DEFAULT_MAXSIZE);
|
||||
|
||||
#define SETOP_NSLOTS 1
|
||||
/* ------------
|
||||
|
||||
/*
|
||||
* Tuple table initialization
|
||||
* ------------
|
||||
*/
|
||||
ExecInitResultTupleSlot(estate, &setopstate->cstate);
|
||||
|
||||
/* ----------------
|
||||
* then initialize outer plan
|
||||
* ----------------
|
||||
/*
|
||||
* then initialize outer plan
|
||||
*/
|
||||
outerPlan = outerPlan((Plan *) node);
|
||||
ExecInitNode(outerPlan, estate, (Plan *) node);
|
||||
|
||||
/* ----------------
|
||||
* setop nodes do no projections, so initialize
|
||||
* projection info for this node appropriately
|
||||
* ----------------
|
||||
/*
|
||||
* setop nodes do no projections, so initialize projection info for
|
||||
* this node appropriately
|
||||
*/
|
||||
ExecAssignResultTypeFromOuterPlan((Plan *) node, &setopstate->cstate);
|
||||
setopstate->cstate.cs_ProjInfo = NULL;
|
||||
|
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/nodeSort.c,v 1.31 2001/01/29 00:39:19 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/nodeSort.c,v 1.32 2001/03/22 06:16:13 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -39,25 +39,22 @@ FormSortKeys(Sort *sortnode)
|
||||
Index reskey;
|
||||
Oid reskeyop;
|
||||
|
||||
/* ----------------
|
||||
* get information from the node
|
||||
* ----------------
|
||||
/*
|
||||
* get information from the node
|
||||
*/
|
||||
targetList = sortnode->plan.targetlist;
|
||||
keycount = sortnode->keycount;
|
||||
|
||||
/* ----------------
|
||||
* first allocate space for scan keys
|
||||
* ----------------
|
||||
/*
|
||||
* first allocate space for scan keys
|
||||
*/
|
||||
if (keycount <= 0)
|
||||
elog(ERROR, "FormSortKeys: keycount <= 0");
|
||||
sortkeys = (ScanKey) palloc(keycount * sizeof(ScanKeyData));
|
||||
MemSet((char *) sortkeys, 0, keycount * sizeof(ScanKeyData));
|
||||
|
||||
/* ----------------
|
||||
* form each scan key from the resdom info in the target list
|
||||
* ----------------
|
||||
/*
|
||||
* form each scan key from the resdom info in the target list
|
||||
*/
|
||||
foreach(tl, targetList)
|
||||
{
|
||||
@@ -106,9 +103,8 @@ ExecSort(Sort *node)
|
||||
TupleTableSlot *slot;
|
||||
bool should_free;
|
||||
|
||||
/* ----------------
|
||||
* get state info from node
|
||||
* ----------------
|
||||
/*
|
||||
* get state info from node
|
||||
*/
|
||||
SO1_printf("ExecSort: %s\n",
|
||||
"entering routine");
|
||||
@@ -118,11 +114,10 @@ ExecSort(Sort *node)
|
||||
dir = estate->es_direction;
|
||||
tuplesortstate = (Tuplesortstate *) sortstate->tuplesortstate;
|
||||
|
||||
/* ----------------
|
||||
* If first time through, read all tuples from outer plan and
|
||||
* pass them to tuplesort.c.
|
||||
* Subsequent calls just fetch tuples from tuplesort.
|
||||
* ----------------
|
||||
/*
|
||||
* If first time through, read all tuples from outer plan and pass
|
||||
* them to tuplesort.c. Subsequent calls just fetch tuples from
|
||||
* tuplesort.
|
||||
*/
|
||||
|
||||
if (!sortstate->sort_Done)
|
||||
@@ -134,17 +129,16 @@ ExecSort(Sort *node)
|
||||
|
||||
SO1_printf("ExecSort: %s\n",
|
||||
"sorting subplan");
|
||||
/* ----------------
|
||||
* Want to scan subplan in the forward direction while creating
|
||||
* the sorted data. (Does setting my direction actually affect
|
||||
* the subplan? I bet this is useless code...)
|
||||
* ----------------
|
||||
|
||||
/*
|
||||
* Want to scan subplan in the forward direction while creating
|
||||
* the sorted data. (Does setting my direction actually affect
|
||||
* the subplan? I bet this is useless code...)
|
||||
*/
|
||||
estate->es_direction = ForwardScanDirection;
|
||||
|
||||
/* ----------------
|
||||
* Initialize tuplesort module.
|
||||
* ----------------
|
||||
/*
|
||||
* Initialize tuplesort module.
|
||||
*/
|
||||
SO1_printf("ExecSort: %s\n",
|
||||
"calling tuplesort_begin");
|
||||
@@ -159,9 +153,8 @@ ExecSort(Sort *node)
|
||||
|
||||
sortstate->tuplesortstate = (void *) tuplesortstate;
|
||||
|
||||
/* ----------------
|
||||
* Scan the subplan and feed all the tuples to tuplesort.
|
||||
* ----------------
|
||||
/*
|
||||
* Scan the subplan and feed all the tuples to tuplesort.
|
||||
*/
|
||||
|
||||
for (;;)
|
||||
@@ -174,27 +167,23 @@ ExecSort(Sort *node)
|
||||
tuplesort_puttuple(tuplesortstate, (void *) slot->val);
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* Complete the sort.
|
||||
* ----------------
|
||||
/*
|
||||
* Complete the sort.
|
||||
*/
|
||||
tuplesort_performsort(tuplesortstate);
|
||||
|
||||
/* ----------------
|
||||
* restore to user specified direction
|
||||
* ----------------
|
||||
/*
|
||||
* restore to user specified direction
|
||||
*/
|
||||
estate->es_direction = dir;
|
||||
|
||||
/* ----------------
|
||||
* make sure the tuple descriptor is up to date (is this needed?)
|
||||
* ----------------
|
||||
/*
|
||||
* make sure the tuple descriptor is up to date (is this needed?)
|
||||
*/
|
||||
ExecAssignResultType(&sortstate->csstate.cstate, tupDesc, false);
|
||||
|
||||
/* ----------------
|
||||
* finally set the sorted flag to true
|
||||
* ----------------
|
||||
/*
|
||||
* finally set the sorted flag to true
|
||||
*/
|
||||
sortstate->sort_Done = true;
|
||||
SO1_printf(stderr, "ExecSort: sorting done.\n");
|
||||
@@ -203,10 +192,9 @@ ExecSort(Sort *node)
|
||||
SO1_printf("ExecSort: %s\n",
|
||||
"retrieving tuple from tuplesort");
|
||||
|
||||
/* ----------------
|
||||
* Get the first or next tuple from tuplesort.
|
||||
* Returns NULL if no more tuples.
|
||||
* ----------------
|
||||
/*
|
||||
* Get the first or next tuple from tuplesort. Returns NULL if no more
|
||||
* tuples.
|
||||
*/
|
||||
heapTuple = tuplesort_getheaptuple(tuplesortstate,
|
||||
ScanDirectionIsForward(dir),
|
||||
@@ -232,15 +220,13 @@ ExecInitSort(Sort *node, EState *estate, Plan *parent)
|
||||
SO1_printf("ExecInitSort: %s\n",
|
||||
"initializing sort node");
|
||||
|
||||
/* ----------------
|
||||
* assign the node's execution state
|
||||
* ----------------
|
||||
/*
|
||||
* assign the node's execution state
|
||||
*/
|
||||
node->plan.state = estate;
|
||||
|
||||
/* ----------------
|
||||
/*
|
||||
* create state structure
|
||||
* ----------------
|
||||
*/
|
||||
sortstate = makeNode(SortState);
|
||||
sortstate->sort_Done = false;
|
||||
@@ -249,42 +235,37 @@ ExecInitSort(Sort *node, EState *estate, Plan *parent)
|
||||
|
||||
node->sortstate = sortstate;
|
||||
|
||||
/* ----------------
|
||||
* Miscellaneous initialization
|
||||
/*
|
||||
* Miscellaneous initialization
|
||||
*
|
||||
* Sort nodes don't initialize their ExprContexts because
|
||||
* they never call ExecQual or ExecProject.
|
||||
* ----------------
|
||||
* Sort nodes don't initialize their ExprContexts because they never call
|
||||
* ExecQual or ExecProject.
|
||||
*/
|
||||
|
||||
#define SORT_NSLOTS 1
|
||||
/* ----------------
|
||||
* tuple table initialization
|
||||
|
||||
/*
|
||||
* tuple table initialization
|
||||
*
|
||||
* sort nodes only return scan tuples from their sorted
|
||||
* relation.
|
||||
* ----------------
|
||||
* sort nodes only return scan tuples from their sorted relation.
|
||||
*/
|
||||
ExecInitResultTupleSlot(estate, &sortstate->csstate.cstate);
|
||||
ExecInitScanTupleSlot(estate, &sortstate->csstate);
|
||||
|
||||
/* ----------------
|
||||
/*
|
||||
* initializes child nodes
|
||||
* ----------------
|
||||
*/
|
||||
outerPlan = outerPlan((Plan *) node);
|
||||
ExecInitNode(outerPlan, estate, (Plan *) node);
|
||||
|
||||
/* ----------------
|
||||
* initialize sortstate information
|
||||
* ----------------
|
||||
/*
|
||||
* initialize sortstate information
|
||||
*/
|
||||
sortstate->sort_Keys = FormSortKeys(node);
|
||||
|
||||
/* ----------------
|
||||
* initialize tuple type. no need to initialize projection
|
||||
* info because this node doesn't do projections.
|
||||
* ----------------
|
||||
/*
|
||||
* initialize tuple type. no need to initialize projection info
|
||||
* because this node doesn't do projections.
|
||||
*/
|
||||
ExecAssignResultTypeFromOuterPlan((Plan *) node, &sortstate->csstate.cstate);
|
||||
ExecAssignScanTypeFromOuterPlan((Plan *) node, &sortstate->csstate);
|
||||
@@ -314,31 +295,27 @@ ExecEndSort(Sort *node)
|
||||
SortState *sortstate;
|
||||
Plan *outerPlan;
|
||||
|
||||
/* ----------------
|
||||
* get info from the sort state
|
||||
* ----------------
|
||||
/*
|
||||
* get info from the sort state
|
||||
*/
|
||||
SO1_printf("ExecEndSort: %s\n",
|
||||
"shutting down sort node");
|
||||
|
||||
sortstate = node->sortstate;
|
||||
|
||||
/* ----------------
|
||||
* shut down the subplan
|
||||
* ----------------
|
||||
/*
|
||||
* shut down the subplan
|
||||
*/
|
||||
outerPlan = outerPlan((Plan *) node);
|
||||
ExecEndNode(outerPlan, (Plan *) node);
|
||||
|
||||
/* ----------------
|
||||
* clean out the tuple table
|
||||
* ----------------
|
||||
/*
|
||||
* clean out the tuple table
|
||||
*/
|
||||
ExecClearTuple(sortstate->csstate.css_ScanTupleSlot);
|
||||
|
||||
/* ----------------
|
||||
* Release tuplesort resources
|
||||
* ----------------
|
||||
/*
|
||||
* Release tuplesort resources
|
||||
*/
|
||||
if (sortstate->tuplesortstate != NULL)
|
||||
tuplesort_end((Tuplesortstate *) sortstate->tuplesortstate);
|
||||
@@ -365,9 +342,8 @@ ExecSortMarkPos(Sort *node)
|
||||
{
|
||||
SortState *sortstate = node->sortstate;
|
||||
|
||||
/* ----------------
|
||||
* if we haven't sorted yet, just return
|
||||
* ----------------
|
||||
/*
|
||||
* if we haven't sorted yet, just return
|
||||
*/
|
||||
if (!sortstate->sort_Done)
|
||||
return;
|
||||
@@ -386,16 +362,14 @@ ExecSortRestrPos(Sort *node)
|
||||
{
|
||||
SortState *sortstate = node->sortstate;
|
||||
|
||||
/* ----------------
|
||||
* if we haven't sorted yet, just return.
|
||||
* ----------------
|
||||
/*
|
||||
* if we haven't sorted yet, just return.
|
||||
*/
|
||||
if (!sortstate->sort_Done)
|
||||
return;
|
||||
|
||||
/* ----------------
|
||||
* restore the scan to the previously marked position
|
||||
* ----------------
|
||||
/*
|
||||
* restore the scan to the previously marked position
|
||||
*/
|
||||
tuplesort_restorepos((Tuplesortstate *) sortstate->tuplesortstate);
|
||||
}
|
||||
|
@@ -12,7 +12,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/nodeSubqueryscan.c,v 1.5 2001/03/22 03:59:29 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/nodeSubqueryscan.c,v 1.6 2001/03/22 06:16:13 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -55,9 +55,8 @@ SubqueryNext(SubqueryScan *node)
|
||||
ScanDirection direction;
|
||||
TupleTableSlot *slot;
|
||||
|
||||
/* ----------------
|
||||
* get information from the estate and scan state
|
||||
* ----------------
|
||||
/*
|
||||
* get information from the estate and scan state
|
||||
*/
|
||||
estate = node->scan.plan.state;
|
||||
subquerystate = (SubqueryScanState *) node->scan.scanstate;
|
||||
@@ -85,9 +84,8 @@ SubqueryNext(SubqueryScan *node)
|
||||
return (slot);
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* get the next tuple from the sub-query
|
||||
* ----------------
|
||||
/*
|
||||
* get the next tuple from the sub-query
|
||||
*/
|
||||
subquerystate->sss_SubEState->es_direction = direction;
|
||||
|
||||
@@ -111,9 +109,9 @@ SubqueryNext(SubqueryScan *node)
|
||||
TupleTableSlot *
|
||||
ExecSubqueryScan(SubqueryScan *node)
|
||||
{
|
||||
/* ----------------
|
||||
* use SubqueryNext as access method
|
||||
* ----------------
|
||||
|
||||
/*
|
||||
* use SubqueryNext as access method
|
||||
*/
|
||||
return ExecScan(&node->scan, (ExecScanAccessMtd) SubqueryNext);
|
||||
}
|
||||
@@ -129,46 +127,41 @@ ExecInitSubqueryScan(SubqueryScan *node, EState *estate, Plan *parent)
|
||||
RangeTblEntry *rte;
|
||||
EState *sp_estate;
|
||||
|
||||
/* ----------------
|
||||
* SubqueryScan should not have any "normal" children.
|
||||
* ----------------
|
||||
/*
|
||||
* SubqueryScan should not have any "normal" children.
|
||||
*/
|
||||
Assert(outerPlan((Plan *) node) == NULL);
|
||||
Assert(innerPlan((Plan *) node) == NULL);
|
||||
|
||||
/* ----------------
|
||||
* assign the node's execution state
|
||||
* ----------------
|
||||
/*
|
||||
* assign the node's execution state
|
||||
*/
|
||||
node->scan.plan.state = estate;
|
||||
|
||||
/* ----------------
|
||||
* create new SubqueryScanState for node
|
||||
* ----------------
|
||||
/*
|
||||
* create new SubqueryScanState for node
|
||||
*/
|
||||
subquerystate = makeNode(SubqueryScanState);
|
||||
node->scan.scanstate = (CommonScanState *) subquerystate;
|
||||
|
||||
/* ----------------
|
||||
* Miscellaneous initialization
|
||||
/*
|
||||
* Miscellaneous initialization
|
||||
*
|
||||
* + create expression context for node
|
||||
* ----------------
|
||||
* create expression context for node
|
||||
*/
|
||||
ExecAssignExprContext(estate, &subquerystate->csstate.cstate);
|
||||
|
||||
#define SUBQUERYSCAN_NSLOTS 2
|
||||
/* ----------------
|
||||
* tuple table initialization
|
||||
* ----------------
|
||||
|
||||
/*
|
||||
* tuple table initialization
|
||||
*/
|
||||
ExecInitResultTupleSlot(estate, &subquerystate->csstate.cstate);
|
||||
|
||||
/* ----------------
|
||||
* initialize subquery
|
||||
/*
|
||||
* initialize subquery
|
||||
*
|
||||
* This should agree with ExecInitSubPlan
|
||||
* ----------------
|
||||
* This should agree with ExecInitSubPlan
|
||||
*/
|
||||
rte = rt_fetch(node->scan.scanrelid, estate->es_range_table);
|
||||
Assert(rte->subquery != NULL);
|
||||
@@ -189,9 +182,8 @@ ExecInitSubqueryScan(SubqueryScan *node, EState *estate, Plan *parent)
|
||||
subquerystate->csstate.css_ScanTupleSlot = NULL;
|
||||
subquerystate->csstate.cstate.cs_TupFromTlist = false;
|
||||
|
||||
/* ----------------
|
||||
* initialize tuple type
|
||||
* ----------------
|
||||
/*
|
||||
* initialize tuple type
|
||||
*/
|
||||
ExecAssignResultTypeFromTL((Plan *) node, &subquerystate->csstate.cstate);
|
||||
ExecAssignProjectionInfo((Plan *) node, &subquerystate->csstate.cstate);
|
||||
@@ -222,27 +214,23 @@ ExecEndSubqueryScan(SubqueryScan *node)
|
||||
{
|
||||
SubqueryScanState *subquerystate;
|
||||
|
||||
/* ----------------
|
||||
* get information from node
|
||||
* ----------------
|
||||
/*
|
||||
* get information from node
|
||||
*/
|
||||
subquerystate = (SubqueryScanState *) node->scan.scanstate;
|
||||
|
||||
/* ----------------
|
||||
* Free the projection info and the scan attribute info
|
||||
/*
|
||||
* Free the projection info and the scan attribute info
|
||||
*
|
||||
* Note: we don't ExecFreeResultType(subquerystate)
|
||||
* because the rule manager depends on the tupType
|
||||
* returned by ExecMain(). So for now, this
|
||||
* is freed at end-transaction time. -cim 6/2/91
|
||||
* ----------------
|
||||
* Note: we don't ExecFreeResultType(subquerystate) because the rule
|
||||
* manager depends on the tupType returned by ExecMain(). So for now,
|
||||
* this is freed at end-transaction time. -cim 6/2/91
|
||||
*/
|
||||
ExecFreeProjectionInfo(&subquerystate->csstate.cstate);
|
||||
ExecFreeExprContext(&subquerystate->csstate.cstate);
|
||||
|
||||
/* ----------------
|
||||
/*
|
||||
* close down subquery
|
||||
* ----------------
|
||||
*/
|
||||
ExecEndNode(node->subplan, node->subplan);
|
||||
|
||||
@@ -250,9 +238,8 @@ ExecEndSubqueryScan(SubqueryScan *node)
|
||||
|
||||
subquerystate->csstate.css_ScanTupleSlot = NULL;
|
||||
|
||||
/* ----------------
|
||||
* clean out the tuple table
|
||||
* ----------------
|
||||
/*
|
||||
* clean out the tuple table
|
||||
*/
|
||||
ExecClearTuple(subquerystate->csstate.cstate.cs_ResultTupleSlot);
|
||||
}
|
||||
|
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/nodeTidscan.c,v 1.15 2001/03/22 03:59:29 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/nodeTidscan.c,v 1.16 2001/03/22 06:16:13 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -83,9 +83,8 @@ TidNext(TidScan *node)
|
||||
ItemPointer *tidList,
|
||||
itemptr;
|
||||
|
||||
/* ----------------
|
||||
* extract necessary information from tid scan node
|
||||
* ----------------
|
||||
/*
|
||||
* extract necessary information from tid scan node
|
||||
*/
|
||||
estate = node->scan.plan.state;
|
||||
direction = estate->es_direction;
|
||||
@@ -120,11 +119,10 @@ TidNext(TidScan *node)
|
||||
|
||||
tuple = &(tidstate->tss_htup);
|
||||
|
||||
/* ----------------
|
||||
* ok, now that we have what we need, fetch an tid tuple.
|
||||
* if scanning this tid succeeded then return the
|
||||
* appropriate heap tuple.. else return NULL.
|
||||
* ----------------
|
||||
/*
|
||||
* ok, now that we have what we need, fetch an tid tuple. if scanning
|
||||
* this tid succeeded then return the appropriate heap tuple.. else
|
||||
* return NULL.
|
||||
*/
|
||||
bBackward = ScanDirectionIsBackward(direction);
|
||||
if (bBackward)
|
||||
@@ -161,13 +159,12 @@ TidNext(TidScan *node)
|
||||
bool prev_matches = false;
|
||||
int prev_tid;
|
||||
|
||||
/* ----------------
|
||||
* store the scanned tuple in the scan tuple slot of
|
||||
* the scan state. Eventually we will only do this and not
|
||||
* return a tuple. Note: we pass 'false' because tuples
|
||||
* returned by amgetnext are pointers onto disk pages and
|
||||
* were not created with palloc() and so should not be pfree()'d.
|
||||
* ----------------
|
||||
/*
|
||||
* store the scanned tuple in the scan tuple slot of the scan
|
||||
* state. Eventually we will only do this and not return a
|
||||
* tuple. Note: we pass 'false' because tuples returned by
|
||||
* amgetnext are pointers onto disk pages and were not created
|
||||
* with palloc() and so should not be pfree()'d.
|
||||
*/
|
||||
ExecStoreTuple(tuple, /* tuple to store */
|
||||
slot,/* slot to store in */
|
||||
@@ -211,10 +208,10 @@ TidNext(TidScan *node)
|
||||
if (slot_is_valid)
|
||||
return slot;
|
||||
}
|
||||
/* ----------------
|
||||
* if we get here it means the tid scan failed so we
|
||||
* are at the end of the scan..
|
||||
* ----------------
|
||||
|
||||
/*
|
||||
* if we get here it means the tid scan failed so we are at the end of
|
||||
* the scan..
|
||||
*/
|
||||
return ExecClearTuple(slot);
|
||||
}
|
||||
@@ -241,9 +238,9 @@ TidNext(TidScan *node)
|
||||
TupleTableSlot *
|
||||
ExecTidScan(TidScan *node)
|
||||
{
|
||||
/* ----------------
|
||||
* use TidNext as access method
|
||||
* ----------------
|
||||
|
||||
/*
|
||||
* use TidNext as access method
|
||||
*/
|
||||
return ExecScan(&node->scan, (ExecScanAccessMtd) TidNext);
|
||||
}
|
||||
@@ -281,9 +278,8 @@ ExecTidReScan(TidScan *node, ExprContext *exprCtxt, Plan *parent)
|
||||
node->scan.scanstate->cstate.cs_ExprContext,
|
||||
tidList);
|
||||
|
||||
/* ----------------
|
||||
* perhaps return something meaningful
|
||||
* ----------------
|
||||
/*
|
||||
* perhaps return something meaningful
|
||||
*/
|
||||
return;
|
||||
}
|
||||
@@ -306,32 +302,27 @@ ExecEndTidScan(TidScan *node)
|
||||
if (tidstate && tidstate->tss_TidList)
|
||||
pfree(tidstate->tss_TidList);
|
||||
|
||||
/* ----------------
|
||||
* extract information from the node
|
||||
* ----------------
|
||||
/*
|
||||
* extract information from the node
|
||||
*/
|
||||
|
||||
/* ----------------
|
||||
* Free the projection info and the scan attribute info
|
||||
/*
|
||||
* Free the projection info and the scan attribute info
|
||||
*
|
||||
* Note: we don't ExecFreeResultType(scanstate)
|
||||
* because the rule manager depends on the tupType
|
||||
* returned by ExecMain(). So for now, this
|
||||
* is freed at end-transaction time. -cim 6/2/91
|
||||
* ----------------
|
||||
* Note: we don't ExecFreeResultType(scanstate) because the rule manager
|
||||
* depends on the tupType returned by ExecMain(). So for now, this is
|
||||
* freed at end-transaction time. -cim 6/2/91
|
||||
*/
|
||||
ExecFreeProjectionInfo(&scanstate->cstate);
|
||||
ExecFreeExprContext(&scanstate->cstate);
|
||||
|
||||
/* ----------------
|
||||
* close the heap and tid relations
|
||||
* ----------------
|
||||
/*
|
||||
* close the heap and tid relations
|
||||
*/
|
||||
ExecCloseR((Plan *) node);
|
||||
|
||||
/* ----------------
|
||||
* clear out tuple table slots
|
||||
* ----------------
|
||||
/*
|
||||
* clear out tuple table slots
|
||||
*/
|
||||
ExecClearTuple(scanstate->cstate.cs_ResultTupleSlot);
|
||||
ExecClearTuple(scanstate->css_ScanTupleSlot);
|
||||
@@ -400,56 +391,50 @@ ExecInitTidScan(TidScan *node, EState *estate, Plan *parent)
|
||||
Relation currentRelation;
|
||||
List *execParam = NIL;
|
||||
|
||||
/* ----------------
|
||||
* assign execution state to node
|
||||
* ----------------
|
||||
/*
|
||||
* assign execution state to node
|
||||
*/
|
||||
node->scan.plan.state = estate;
|
||||
|
||||
/* --------------------------------
|
||||
* Part 1) initialize scan state
|
||||
/*
|
||||
* Part 1) initialize scan state
|
||||
*
|
||||
* create new CommonScanState for node
|
||||
* --------------------------------
|
||||
* create new CommonScanState for node
|
||||
*/
|
||||
scanstate = makeNode(CommonScanState);
|
||||
node->scan.scanstate = scanstate;
|
||||
|
||||
/* ----------------
|
||||
* Miscellaneous initialization
|
||||
/*
|
||||
* Miscellaneous initialization
|
||||
*
|
||||
* + create expression context for node
|
||||
* ----------------
|
||||
* create expression context for node
|
||||
*/
|
||||
ExecAssignExprContext(estate, &scanstate->cstate);
|
||||
|
||||
#define TIDSCAN_NSLOTS 3
|
||||
/* ----------------
|
||||
* tuple table initialization
|
||||
* ----------------
|
||||
|
||||
/*
|
||||
* tuple table initialization
|
||||
*/
|
||||
ExecInitResultTupleSlot(estate, &scanstate->cstate);
|
||||
ExecInitScanTupleSlot(estate, scanstate);
|
||||
|
||||
/* ----------------
|
||||
* initialize projection info. result type comes from scan desc
|
||||
* below..
|
||||
* ----------------
|
||||
/*
|
||||
* initialize projection info. result type comes from scan desc
|
||||
* below..
|
||||
*/
|
||||
ExecAssignProjectionInfo((Plan *) node, &scanstate->cstate);
|
||||
|
||||
/* --------------------------------
|
||||
* Part 2) initialize tid scan state
|
||||
*
|
||||
* create new TidScanState for node
|
||||
* --------------------------------
|
||||
*/
|
||||
/*
|
||||
* Part 2) initialize tid scan state
|
||||
*
|
||||
* create new TidScanState for node
|
||||
*/
|
||||
tidstate = makeNode(TidScanState);
|
||||
node->tidstate = tidstate;
|
||||
|
||||
/* ----------------
|
||||
* get the tid node information
|
||||
* ----------------
|
||||
/*
|
||||
* get the tid node information
|
||||
*/
|
||||
tidList = (ItemPointer *) palloc(length(node->tideval) * sizeof(ItemPointer));
|
||||
numTids = 0;
|
||||
@@ -463,17 +448,14 @@ ExecInitTidScan(TidScan *node, EState *estate, Plan *parent)
|
||||
tidstate->tss_TidPtr = tidPtr;
|
||||
tidstate->tss_TidList = tidList;
|
||||
|
||||
/* ----------------
|
||||
* get the range table and direction information
|
||||
* from the execution state (these are needed to
|
||||
* open the relations).
|
||||
* ----------------
|
||||
/*
|
||||
* get the range table and direction information from the execution
|
||||
* state (these are needed to open the relations).
|
||||
*/
|
||||
rangeTable = estate->es_range_table;
|
||||
|
||||
/* ----------------
|
||||
* open the base relation
|
||||
* ----------------
|
||||
/*
|
||||
* open the base relation
|
||||
*/
|
||||
relid = node->scan.scanrelid;
|
||||
rtentry = rt_fetch(relid, rangeTable);
|
||||
@@ -483,9 +465,8 @@ ExecInitTidScan(TidScan *node, EState *estate, Plan *parent)
|
||||
scanstate->css_currentRelation = currentRelation;
|
||||
scanstate->css_currentScanDesc = 0;
|
||||
|
||||
/* ----------------
|
||||
* get the scan type from the relation descriptor.
|
||||
* ----------------
|
||||
/*
|
||||
* get the scan type from the relation descriptor.
|
||||
*/
|
||||
ExecAssignScanType(scanstate, RelationGetDescr(currentRelation), false);
|
||||
ExecAssignResultTypeFromTL((Plan *) node, &scanstate->cstate);
|
||||
@@ -496,9 +477,8 @@ ExecInitTidScan(TidScan *node, EState *estate, Plan *parent)
|
||||
*/
|
||||
((Plan *) node)->chgParam = execParam;
|
||||
|
||||
/* ----------------
|
||||
* all done.
|
||||
* ----------------
|
||||
/*
|
||||
* all done.
|
||||
*/
|
||||
return TRUE;
|
||||
}
|
||||
|
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/nodeUnique.c,v 1.31 2001/01/24 19:42:55 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/nodeUnique.c,v 1.32 2001/03/22 06:16:13 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -47,43 +47,38 @@ ExecUnique(Unique *node)
|
||||
Plan *outerPlan;
|
||||
TupleDesc tupDesc;
|
||||
|
||||
/* ----------------
|
||||
* get information from the node
|
||||
* ----------------
|
||||
/*
|
||||
* get information from the node
|
||||
*/
|
||||
uniquestate = node->uniquestate;
|
||||
outerPlan = outerPlan((Plan *) node);
|
||||
resultTupleSlot = uniquestate->cstate.cs_ResultTupleSlot;
|
||||
tupDesc = ExecGetResultType(&uniquestate->cstate);
|
||||
|
||||
/* ----------------
|
||||
* now loop, returning only non-duplicate tuples.
|
||||
* We assume that the tuples arrive in sorted order
|
||||
* so we can detect duplicates easily.
|
||||
* ----------------
|
||||
/*
|
||||
* now loop, returning only non-duplicate tuples. We assume that the
|
||||
* tuples arrive in sorted order so we can detect duplicates easily.
|
||||
*/
|
||||
for (;;)
|
||||
{
|
||||
/* ----------------
|
||||
* fetch a tuple from the outer subplan
|
||||
* ----------------
|
||||
|
||||
/*
|
||||
* fetch a tuple from the outer subplan
|
||||
*/
|
||||
slot = ExecProcNode(outerPlan, (Plan *) node);
|
||||
if (TupIsNull(slot))
|
||||
return NULL;
|
||||
|
||||
/* ----------------
|
||||
* Always return the first tuple from the subplan.
|
||||
* ----------------
|
||||
/*
|
||||
* Always return the first tuple from the subplan.
|
||||
*/
|
||||
if (uniquestate->priorTuple == NULL)
|
||||
break;
|
||||
|
||||
/* ----------------
|
||||
* Else test if the new tuple and the previously returned
|
||||
* tuple match. If so then we loop back and fetch
|
||||
* another new tuple from the subplan.
|
||||
* ----------------
|
||||
/*
|
||||
* Else test if the new tuple and the previously returned tuple
|
||||
* match. If so then we loop back and fetch another new tuple
|
||||
* from the subplan.
|
||||
*/
|
||||
if (!execTuplesMatch(slot->val, uniquestate->priorTuple,
|
||||
tupDesc,
|
||||
@@ -93,18 +88,17 @@ ExecUnique(Unique *node)
|
||||
break;
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* We have a new tuple different from the previous saved tuple (if any).
|
||||
* Save it and return it. We must copy it because the source subplan
|
||||
* won't guarantee that this source tuple is still accessible after
|
||||
* fetching the next source tuple.
|
||||
/*
|
||||
* We have a new tuple different from the previous saved tuple (if
|
||||
* any). Save it and return it. We must copy it because the source
|
||||
* subplan won't guarantee that this source tuple is still accessible
|
||||
* after fetching the next source tuple.
|
||||
*
|
||||
* Note that we manage the copy ourselves. We can't rely on the result
|
||||
* tuple slot to maintain the tuple reference because our caller may
|
||||
* replace the slot contents with a different tuple (see junk filter
|
||||
* handling in execMain.c). We assume that the caller will no longer
|
||||
* be interested in the current tuple after he next calls us.
|
||||
* ----------------
|
||||
* Note that we manage the copy ourselves. We can't rely on the result
|
||||
* tuple slot to maintain the tuple reference because our caller may
|
||||
* replace the slot contents with a different tuple (see junk filter
|
||||
* handling in execMain.c). We assume that the caller will no longer
|
||||
* be interested in the current tuple after he next calls us.
|
||||
*/
|
||||
if (uniquestate->priorTuple != NULL)
|
||||
heap_freetuple(uniquestate->priorTuple);
|
||||
@@ -131,27 +125,24 @@ ExecInitUnique(Unique *node, EState *estate, Plan *parent)
|
||||
UniqueState *uniquestate;
|
||||
Plan *outerPlan;
|
||||
|
||||
/* ----------------
|
||||
* assign execution state to node
|
||||
* ----------------
|
||||
/*
|
||||
* assign execution state to node
|
||||
*/
|
||||
node->plan.state = estate;
|
||||
|
||||
/* ----------------
|
||||
* create new UniqueState for node
|
||||
* ----------------
|
||||
/*
|
||||
* create new UniqueState for node
|
||||
*/
|
||||
uniquestate = makeNode(UniqueState);
|
||||
node->uniquestate = uniquestate;
|
||||
uniquestate->priorTuple = NULL;
|
||||
|
||||
/* ----------------
|
||||
* Miscellaneous initialization
|
||||
/*
|
||||
* Miscellaneous initialization
|
||||
*
|
||||
* Unique nodes have no ExprContext initialization because
|
||||
* they never call ExecQual or ExecProject. But they do need a
|
||||
* per-tuple memory context anyway for calling execTuplesMatch.
|
||||
* ----------------
|
||||
* Unique nodes have no ExprContext initialization because they never
|
||||
* call ExecQual or ExecProject. But they do need a per-tuple memory
|
||||
* context anyway for calling execTuplesMatch.
|
||||
*/
|
||||
uniquestate->tempContext =
|
||||
AllocSetContextCreate(CurrentMemoryContext,
|
||||
@@ -161,23 +152,21 @@ ExecInitUnique(Unique *node, EState *estate, Plan *parent)
|
||||
ALLOCSET_DEFAULT_MAXSIZE);
|
||||
|
||||
#define UNIQUE_NSLOTS 1
|
||||
/* ------------
|
||||
|
||||
/*
|
||||
* Tuple table initialization
|
||||
* ------------
|
||||
*/
|
||||
ExecInitResultTupleSlot(estate, &uniquestate->cstate);
|
||||
|
||||
/* ----------------
|
||||
* then initialize outer plan
|
||||
* ----------------
|
||||
/*
|
||||
* then initialize outer plan
|
||||
*/
|
||||
outerPlan = outerPlan((Plan *) node);
|
||||
ExecInitNode(outerPlan, estate, (Plan *) node);
|
||||
|
||||
/* ----------------
|
||||
* unique nodes do no projections, so initialize
|
||||
* projection info for this node appropriately
|
||||
* ----------------
|
||||
/*
|
||||
* unique nodes do no projections, so initialize projection info for
|
||||
* this node appropriately
|
||||
*/
|
||||
ExecAssignResultTypeFromOuterPlan((Plan *) node, &uniquestate->cstate);
|
||||
uniquestate->cstate.cs_ProjInfo = NULL;
|
||||
|
Reference in New Issue
Block a user