postgresql/src/backend/executor/nodeMaterial.c

414 lines
11 KiB
C
Raw Normal View History

/*-------------------------------------------------------------------------
*
* nodeMaterial.c
* Routines to handle materialization nodes.
*
* Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
2000-01-05 19:23:54 +01:00
* $Header: /cvsroot/pgsql/src/backend/executor/nodeMaterial.c,v 1.28 2000/01/05 18:23:46 momjian Exp $
*
*-------------------------------------------------------------------------
*/
/*
* INTERFACE ROUTINES
* ExecMaterial - generate a temporary relation
* ExecInitMaterial - initialize node and subnodes..
* ExecEndMaterial - shutdown node and subnodes
*
*/
#include "postgres.h"
1999-07-16 07:00:38 +02:00
#include "access/heapam.h"
#include "catalog/heap.h"
#include "executor/executor.h"
#include "executor/nodeMaterial.h"
1999-07-16 05:14:30 +02:00
#include "optimizer/internal.h"
/* ----------------------------------------------------------------
* ExecMaterial
*
* The first time this is called, ExecMaterial retrieves tuples
* from this node's outer subplan and inserts them into a temporary
* relation. After this is done, a flag is set indicating that
* the subplan has been materialized. Once the relation is
* materialized, the first tuple is then returned. Successive
* calls to ExecMaterial return successive tuples from the temp
* relation.
*
* Initial State:
*
* ExecMaterial assumes the temporary relation has been
* created and opened by ExecInitMaterial during the prior
* InitPlan() phase.
*
* ----------------------------------------------------------------
*/
TupleTableSlot * /* result tuple from subplan */
ExecMaterial(Material *node)
{
EState *estate;
MaterialState *matstate;
Plan *outerNode;
ScanDirection dir;
Relation tempRelation;
Relation currentRelation;
HeapScanDesc currentScanDesc;
HeapTuple heapTuple;
TupleTableSlot *slot;
/* ----------------
* get state info from node
* ----------------
*/
matstate = node->matstate;
estate = node->plan.state;
dir = estate->es_direction;
/* ----------------
* the first time we call this, we retrieve all tuples
* from the subplan into a temporary relation and then
* we sort the relation. Subsequent calls return tuples
* from the temporary relation.
* ----------------
*/
if (matstate->mat_Flag == false)
{
/* ----------------
* set all relations to be scanned in the forward direction
* while creating the temporary relation.
* ----------------
*/
estate->es_direction = ForwardScanDirection;
/* ----------------
* if we couldn't create the temp or current relations then
* we print a warning and return NULL.
* ----------------
*/
tempRelation = matstate->mat_TempRelation;
if (tempRelation == NULL)
{
elog(DEBUG, "ExecMaterial: temp relation is NULL! aborting...");
return NULL;
}
currentRelation = matstate->csstate.css_currentRelation;
if (currentRelation == NULL)
{
elog(DEBUG, "ExecMaterial: current relation is NULL! aborting...");
return NULL;
}
/* ----------------
* retrieve tuples from the subplan and
* insert them in the temporary relation
* ----------------
*/
outerNode = outerPlan((Plan *) node);
for (;;)
{
slot = ExecProcNode(outerNode, (Plan *) node);
1998-11-27 20:52:36 +01:00
if (TupIsNull(slot))
break;
1999-05-25 18:15:34 +02:00
heap_insert(tempRelation, slot->val);
1999-05-25 18:15:34 +02:00
ExecClearTuple(slot);
}
currentRelation = tempRelation;
/* ----------------
* restore to user specified direction
* ----------------
*/
estate->es_direction = dir;
/* ----------------
* now initialize the scan descriptor to scan the
* sorted relation and update the sortstate information
* ----------------
*/
currentScanDesc = heap_beginscan(currentRelation, /* relation */
ScanDirectionIsBackward(dir),
1998-07-27 21:38:40 +02:00
SnapshotSelf, /* seeself */
0, /* num scan keys */
NULL); /* scan keys */
matstate->csstate.css_currentRelation = currentRelation;
matstate->csstate.css_currentScanDesc = currentScanDesc;
ExecAssignScanType(&matstate->csstate,
1998-09-01 05:29:17 +02:00
RelationGetDescr(currentRelation));
/* ----------------
* finally set the sorted flag to true
* ----------------
*/
matstate->mat_Flag = true;
}
/* ----------------
* at this point we know we have a sorted relation so
* we perform a simple scan on it with amgetnext()..
* ----------------
*/
currentScanDesc = matstate->csstate.css_currentScanDesc;
heapTuple = heap_getnext(currentScanDesc, ScanDirectionIsBackward(dir));
/* ----------------
* put the tuple into the scan tuple slot and return the slot.
* Note: since the tuple is really a pointer to a page, we don't want
* to call pfree() on it..
* ----------------
*/
slot = (TupleTableSlot *) matstate->csstate.css_ScanTupleSlot;
return ExecStoreTuple(heapTuple, /* tuple to store */
slot, /* slot to store in */
currentScanDesc->rs_cbuf, /* buffer for this tuple */
false); /* don't pfree this pointer */
}
/* ----------------------------------------------------------------
* ExecInitMaterial
* ----------------------------------------------------------------
*/
bool /* initialization status */
ExecInitMaterial(Material *node, EState *estate, Plan *parent)
{
MaterialState *matstate;
Plan *outerPlan;
TupleDesc tupType;
Relation tempDesc;
/* int len; */
/* ----------------
* assign the node's execution state
* ----------------
*/
node->plan.state = estate;
/* ----------------
* create state structure
* ----------------
*/
matstate = makeNode(MaterialState);
matstate->mat_Flag = false;
matstate->mat_TempRelation = NULL;
node->matstate = matstate;
/* ----------------
* Miscellanious initialization
*
* + assign node's base_id
* + assign debugging hooks and
* + assign result tuple slot
*
* Materialization nodes don't need ExprContexts because
* they never call ExecQual or ExecTargetList.
* ----------------
*/
ExecAssignNodeBaseInfo(estate, &matstate->csstate.cstate, parent);
#define MATERIAL_NSLOTS 1
/* ----------------
* tuple table initialization
* ----------------
*/
ExecInitScanTupleSlot(estate, &matstate->csstate);
/* ----------------
* initializes child nodes
* ----------------
*/
outerPlan = outerPlan((Plan *) node);
ExecInitNode(outerPlan, estate, (Plan *) node);
/* ----------------
* initialize matstate information
* ----------------
*/
matstate->mat_Flag = false;
/* ----------------
* initialize tuple type. no need to initialize projection
* info because this node doesn't do projections.
* ----------------
*/
ExecAssignScanTypeFromOuterPlan((Plan *) node, &matstate->csstate);
matstate->csstate.cstate.cs_ProjInfo = NULL;
/* ----------------
* get type information needed for ExecCreatR
* ----------------
*/
tupType = ExecGetScanType(&matstate->csstate);
/* ----------------
2000-01-05 19:23:54 +01:00
* ExecCreatR wants its second argument to be an object id of
* a relation in the range table or a _NONAME_RELATION_ID
* indicating that the relation is not in the range table.
*
* In the second case ExecCreatR creates a temp relation.
* (currently this is the only case we support -cim 10/16/89)
* ----------------
*/
/* ----------------
* create the temporary relation
* ----------------
*/
/* len = ExecTargetListLength(node->plan.targetlist); */
tempDesc = ExecCreatR(tupType, _NONAME_RELATION_ID_);
/* ----------------
* save the relation descriptor in the sortstate
* ----------------
*/
matstate->mat_TempRelation = tempDesc;
matstate->csstate.css_currentRelation = tempDesc;
/* ----------------
* return relation oid of temporary relation in a list
* (someday -- for now we return LispTrue... cim 10/12/89)
* ----------------
*/
return TRUE;
}
int
ExecCountSlotsMaterial(Material *node)
{
return ExecCountSlotsNode(outerPlan((Plan *) node)) +
ExecCountSlotsNode(innerPlan((Plan *) node)) +
MATERIAL_NSLOTS;
}
/* ----------------------------------------------------------------
* ExecEndMaterial
*
* old comments
* destroys the temporary relation.
* ----------------------------------------------------------------
*/
void
ExecEndMaterial(Material *node)
{
MaterialState *matstate;
Relation tempRelation;
Plan *outerPlan;
/* ----------------
* get info from the material state
* ----------------
*/
matstate = node->matstate;
tempRelation = matstate->mat_TempRelation;
heap_drop(tempRelation);
/* ----------------
* close the temp relation and shut down the scan.
* ----------------
*/
ExecCloseR((Plan *) node);
/* ----------------
* shut down the subplan
* ----------------
*/
outerPlan = outerPlan((Plan *) node);
ExecEndNode(outerPlan, (Plan *) node);
/* ----------------
* clean out the tuple table
* ----------------
*/
ExecClearTuple(matstate->csstate.css_ScanTupleSlot);
}
/* ----------------------------------------------------------------
* ExecMaterialReScan
*
* Rescans the temporary relation.
* ----------------------------------------------------------------
*/
void
ExecMaterialReScan(Material *node, ExprContext *exprCtxt, Plan *parent)
{
MaterialState *matstate = node->matstate;
if (matstate->mat_Flag == false)
return;
matstate->csstate.css_currentScanDesc = ExecReScanR(matstate->csstate.css_currentRelation,
1999-05-25 18:15:34 +02:00
matstate->csstate.css_currentScanDesc,
node->plan.state->es_direction, 0, NULL);
}
#ifdef NOT_USED /* not used */
/* ----------------------------------------------------------------
* ExecMaterialMarkPos
* ----------------------------------------------------------------
*/
List /* nothing of interest */
ExecMaterialMarkPos(Material node)
{
MaterialState matstate;
HeapScanDesc scan;
/* ----------------
* if we haven't materialized yet, just return NIL.
* ----------------
*/
matstate = get_matstate(node);
if (get_mat_Flag(matstate) == false)
return NIL;
/* ----------------
* XXX access methods don't return positions yet so
* for now we return NIL. It's possible that
* they will never return positions for all I know -cim 10/16/89
* ----------------
*/
scan = get_css_currentScanDesc((CommonScanState) matstate);
heap_markpos(scan);
return NIL;
}
/* ----------------------------------------------------------------
* ExecMaterialRestrPos
* ----------------------------------------------------------------
*/
void
ExecMaterialRestrPos(Material node)
{
MaterialState matstate;
HeapScanDesc scan;
/* ----------------
* if we haven't materialized yet, just return.
* ----------------
*/
matstate = get_matstate(node);
if (get_mat_Flag(matstate) == false)
return;
/* ----------------
* restore the scan to the previously marked position
* ----------------
*/
scan = get_css_currentScanDesc((CommonScanState) matstate);
heap_restrpos(scan);
}
#endif