1
0
mirror of https://github.com/postgres/postgres.git synced 2025-05-09 18:21:05 +03:00
PostgreSQL Daemon 2ff501590b Tag appropriate files for rc3
Also performed an initial run through of upgrading our Copyright date to
extend to 2005 ... first run here was very simple ... change everything
where: grep 1996-2004 && the word 'Copyright' ... scanned through the
generated list with 'less' first, and after, to make sure that I only
picked up the right entries ...
2004-12-31 22:04:05 +00:00

416 lines
9.9 KiB
C

/*-------------------------------------------------------------------------
*
* execAmi.c
* miscellaneous executor access method routines
*
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/backend/executor/execAmi.c,v 1.82 2004/12/31 21:59:45 pgsql Exp $
*
*-------------------------------------------------------------------------
*/
#include "postgres.h"
#include "access/genam.h"
#include "access/heapam.h"
#include "catalog/heap.h"
#include "executor/execdebug.h"
#include "executor/instrument.h"
#include "executor/nodeAgg.h"
#include "executor/nodeAppend.h"
#include "executor/nodeFunctionscan.h"
#include "executor/nodeGroup.h"
#include "executor/nodeGroup.h"
#include "executor/nodeHash.h"
#include "executor/nodeHashjoin.h"
#include "executor/nodeIndexscan.h"
#include "executor/nodeLimit.h"
#include "executor/nodeMaterial.h"
#include "executor/nodeMergejoin.h"
#include "executor/nodeNestloop.h"
#include "executor/nodeResult.h"
#include "executor/nodeSeqscan.h"
#include "executor/nodeSetOp.h"
#include "executor/nodeSort.h"
#include "executor/nodeSubplan.h"
#include "executor/nodeSubqueryscan.h"
#include "executor/nodeTidscan.h"
#include "executor/nodeUnique.h"
/*
* ExecReScan
* Reset a plan node so that its output can be re-scanned.
*
* Note that if the plan node has parameters that have changed value,
* the output might be different from last time.
*
* The second parameter is currently only used to pass a NestLoop plan's
* econtext down to its inner child plan, in case that is an indexscan that
* needs access to variables of the current outer tuple. (The handling of
* this parameter is currently pretty inconsistent: some callers pass NULL
* and some pass down their parent's value; so don't rely on it in other
* situations. It'd probably be better to remove the whole thing and use
* the generalized parameter mechanism instead.)
*/
void
ExecReScan(PlanState *node, ExprContext *exprCtxt)
{
/* If collecting timing stats, update them */
if (node->instrument)
InstrEndLoop(node->instrument);
/* If we have changed parameters, propagate that info */
if (node->chgParam != NULL)
{
ListCell *l;
foreach(l, node->initPlan)
{
SubPlanState *sstate = (SubPlanState *) lfirst(l);
PlanState *splan = sstate->planstate;
if (splan->plan->extParam != NULL) /* don't care about child
* local Params */
UpdateChangedParamSet(splan, node->chgParam);
if (splan->chgParam != NULL)
ExecReScanSetParamPlan(sstate, node);
}
foreach(l, node->subPlan)
{
SubPlanState *sstate = (SubPlanState *) lfirst(l);
PlanState *splan = sstate->planstate;
if (splan->plan->extParam != NULL)
UpdateChangedParamSet(splan, node->chgParam);
}
/* Well. Now set chgParam for left/right trees. */
if (node->lefttree != NULL)
UpdateChangedParamSet(node->lefttree, node->chgParam);
if (node->righttree != NULL)
UpdateChangedParamSet(node->righttree, node->chgParam);
}
/* Shut down any SRFs in the plan node's targetlist */
if (node->ps_ExprContext)
ReScanExprContext(node->ps_ExprContext);
/* And do node-type-specific processing */
switch (nodeTag(node))
{
case T_ResultState:
ExecReScanResult((ResultState *) node, exprCtxt);
break;
case T_AppendState:
ExecReScanAppend((AppendState *) node, exprCtxt);
break;
case T_SeqScanState:
ExecSeqReScan((SeqScanState *) node, exprCtxt);
break;
case T_IndexScanState:
ExecIndexReScan((IndexScanState *) node, exprCtxt);
break;
case T_TidScanState:
ExecTidReScan((TidScanState *) node, exprCtxt);
break;
case T_SubqueryScanState:
ExecSubqueryReScan((SubqueryScanState *) node, exprCtxt);
break;
case T_FunctionScanState:
ExecFunctionReScan((FunctionScanState *) node, exprCtxt);
break;
case T_NestLoopState:
ExecReScanNestLoop((NestLoopState *) node, exprCtxt);
break;
case T_MergeJoinState:
ExecReScanMergeJoin((MergeJoinState *) node, exprCtxt);
break;
case T_HashJoinState:
ExecReScanHashJoin((HashJoinState *) node, exprCtxt);
break;
case T_MaterialState:
ExecMaterialReScan((MaterialState *) node, exprCtxt);
break;
case T_SortState:
ExecReScanSort((SortState *) node, exprCtxt);
break;
case T_GroupState:
ExecReScanGroup((GroupState *) node, exprCtxt);
break;
case T_AggState:
ExecReScanAgg((AggState *) node, exprCtxt);
break;
case T_UniqueState:
ExecReScanUnique((UniqueState *) node, exprCtxt);
break;
case T_HashState:
ExecReScanHash((HashState *) node, exprCtxt);
break;
case T_SetOpState:
ExecReScanSetOp((SetOpState *) node, exprCtxt);
break;
case T_LimitState:
ExecReScanLimit((LimitState *) node, exprCtxt);
break;
default:
elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node));
break;
}
if (node->chgParam != NULL)
{
bms_free(node->chgParam);
node->chgParam = NULL;
}
}
/*
* ExecMarkPos
*
* Marks the current scan position.
*/
void
ExecMarkPos(PlanState *node)
{
switch (nodeTag(node))
{
case T_SeqScanState:
ExecSeqMarkPos((SeqScanState *) node);
break;
case T_IndexScanState:
ExecIndexMarkPos((IndexScanState *) node);
break;
case T_TidScanState:
ExecTidMarkPos((TidScanState *) node);
break;
case T_FunctionScanState:
ExecFunctionMarkPos((FunctionScanState *) node);
break;
case T_MaterialState:
ExecMaterialMarkPos((MaterialState *) node);
break;
case T_SortState:
ExecSortMarkPos((SortState *) node);
break;
default:
/* don't make hard error unless caller asks to restore... */
elog(DEBUG2, "unrecognized node type: %d", (int) nodeTag(node));
break;
}
}
/*
* ExecRestrPos
*
* restores the scan position previously saved with ExecMarkPos()
*/
void
ExecRestrPos(PlanState *node)
{
switch (nodeTag(node))
{
case T_SeqScanState:
ExecSeqRestrPos((SeqScanState *) node);
break;
case T_IndexScanState:
ExecIndexRestrPos((IndexScanState *) node);
break;
case T_TidScanState:
ExecTidRestrPos((TidScanState *) node);
break;
case T_FunctionScanState:
ExecFunctionRestrPos((FunctionScanState *) node);
break;
case T_MaterialState:
ExecMaterialRestrPos((MaterialState *) node);
break;
case T_SortState:
ExecSortRestrPos((SortState *) node);
break;
default:
elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node));
break;
}
}
/*
* ExecSupportsMarkRestore - does a plan type support mark/restore?
*
* XXX Ideally, all plan node types would support mark/restore, and this
* wouldn't be needed. For now, this had better match the routines above.
* But note the test is on Plan nodetype, not PlanState nodetype.
*/
bool
ExecSupportsMarkRestore(NodeTag plantype)
{
switch (plantype)
{
case T_SeqScan:
case T_IndexScan:
case T_TidScan:
case T_FunctionScan:
case T_Material:
case T_Sort:
return true;
default:
break;
}
return false;
}
/*
* ExecSupportsBackwardScan - does a plan type support backwards scanning?
*
* Ideally, all plan types would support backwards scan, but that seems
* unlikely to happen soon. In some cases, a plan node passes the backwards
* scan down to its children, and so supports backwards scan only if its
* children do. Therefore, this routine must be passed a complete plan tree.
*/
bool
ExecSupportsBackwardScan(Plan *node)
{
if (node == NULL)
return false;
switch (nodeTag(node))
{
case T_Result:
if (outerPlan(node) != NULL)
return ExecSupportsBackwardScan(outerPlan(node));
else
return false;
case T_Append:
{
ListCell *l;
foreach(l, ((Append *) node)->appendplans)
{
if (!ExecSupportsBackwardScan((Plan *) lfirst(l)))
return false;
}
return true;
}
case T_SeqScan:
case T_IndexScan:
case T_TidScan:
case T_FunctionScan:
return true;
case T_SubqueryScan:
return ExecSupportsBackwardScan(((SubqueryScan *) node)->subplan);
case T_Material:
case T_Sort:
return true;
case T_Unique:
return ExecSupportsBackwardScan(outerPlan(node));
case T_Limit:
return ExecSupportsBackwardScan(outerPlan(node));
default:
return false;
}
}
/*
* ExecMayReturnRawTuples
* Check whether a plan tree may return "raw" disk tuples (that is,
* pointers to original data in disk buffers, as opposed to temporary
* tuples constructed by projection steps). In the case of Append,
* some subplans may return raw tuples and others projected tuples;
* we return "true" if any of the returned tuples could be raw.
*
* This must be passed an already-initialized planstate tree, because we
* need to look at the results of ExecAssignScanProjectionInfo().
*/
bool
ExecMayReturnRawTuples(PlanState *node)
{
/*
* At a table scan node, we check whether ExecAssignScanProjectionInfo
* decided to do projection or not. Most non-scan nodes always
* project and so we can return "false" immediately. For nodes that
* don't project but just pass up input tuples, we have to recursively
* examine the input plan node.
*
* Note: Hash and Material are listed here because they sometimes return
* an original input tuple, not a copy. But Sort and SetOp never
* return an original tuple, so they can be treated like projecting
* nodes.
*/
switch (nodeTag(node))
{
/* Table scan nodes */
case T_SeqScanState:
case T_IndexScanState:
case T_TidScanState:
case T_SubqueryScanState:
case T_FunctionScanState:
if (node->ps_ProjInfo == NULL)
return true;
break;
/* Non-projecting nodes */
case T_HashState:
case T_MaterialState:
case T_UniqueState:
case T_LimitState:
return ExecMayReturnRawTuples(node->lefttree);
case T_AppendState:
{
AppendState *appendstate = (AppendState *) node;
int j;
for (j = 0; j < appendstate->as_nplans; j++)
{
if (ExecMayReturnRawTuples(appendstate->appendplans[j]))
return true;
}
break;
}
/* All projecting node types come here */
default:
break;
}
return false;
}