1996-07-09 08:22:35 +02:00
|
|
|
/*-------------------------------------------------------------------------
|
|
|
|
*
|
1999-02-14 00:22:53 +01:00
|
|
|
* execAmi.c
|
1999-09-18 21:08:25 +02:00
|
|
|
* miscellaneous executor access method routines
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
2016-01-02 19:33:40 +01:00
|
|
|
* Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
|
2000-01-26 06:58:53 +01:00
|
|
|
* Portions Copyright (c) 1994, Regents of the University of California
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
2010-09-20 22:08:53 +02:00
|
|
|
* src/backend/executor/execAmi.c
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
|
|
|
*-------------------------------------------------------------------------
|
|
|
|
*/
|
1996-10-31 11:12:26 +01:00
|
|
|
#include "postgres.h"
|
|
|
|
|
2012-08-30 22:15:44 +02:00
|
|
|
#include "access/htup_details.h"
|
1999-07-16 07:00:38 +02:00
|
|
|
#include "executor/execdebug.h"
|
|
|
|
#include "executor/nodeAgg.h"
|
|
|
|
#include "executor/nodeAppend.h"
|
2005-04-20 00:35:18 +02:00
|
|
|
#include "executor/nodeBitmapAnd.h"
|
|
|
|
#include "executor/nodeBitmapHeapscan.h"
|
|
|
|
#include "executor/nodeBitmapIndexscan.h"
|
|
|
|
#include "executor/nodeBitmapOr.h"
|
2008-12-28 19:54:01 +01:00
|
|
|
#include "executor/nodeCtescan.h"
|
2014-11-07 23:26:02 +01:00
|
|
|
#include "executor/nodeCustom.h"
|
2011-02-20 06:17:18 +01:00
|
|
|
#include "executor/nodeForeignscan.h"
|
2002-12-05 16:50:39 +01:00
|
|
|
#include "executor/nodeFunctionscan.h"
|
Add a Gather executor node.
A Gather executor node runs any number of copies of a plan in an equal
number of workers and merges all of the results into a single tuple
stream. It can also run the plan itself, if the workers are
unavailable or haven't started up yet. It is intended to work with
the Partial Seq Scan node which will be added in future commits.
It could also be used to implement parallel query of a different sort
by itself, without help from Partial Seq Scan, if the single_copy mode
is used. In that mode, a worker executes the plan, and the parallel
leader does not, merely collecting the worker's results. So, a Gather
node could be inserted into a plan to split the execution of that plan
across two processes. Nested Gather nodes aren't currently supported,
but we might want to add support for that in the future.
There's nothing in the planner to actually generate Gather nodes yet,
so it's not quite time to break out the champagne. But we're getting
close.
Amit Kapila. Some designs suggestions were provided by me, and I also
reviewed the patch. Single-copy mode, documentation, and other minor
changes also by me.
2015-10-01 01:23:36 +02:00
|
|
|
#include "executor/nodeGather.h"
|
1999-07-16 07:00:38 +02:00
|
|
|
#include "executor/nodeGroup.h"
|
|
|
|
#include "executor/nodeGroup.h"
|
|
|
|
#include "executor/nodeHash.h"
|
|
|
|
#include "executor/nodeHashjoin.h"
|
2011-10-11 20:20:06 +02:00
|
|
|
#include "executor/nodeIndexonlyscan.h"
|
1996-07-09 08:22:35 +02:00
|
|
|
#include "executor/nodeIndexscan.h"
|
2000-10-26 23:38:24 +02:00
|
|
|
#include "executor/nodeLimit.h"
|
2009-10-12 20:10:51 +02:00
|
|
|
#include "executor/nodeLockRows.h"
|
1998-02-13 04:26:53 +01:00
|
|
|
#include "executor/nodeMaterial.h"
|
2010-10-14 22:56:39 +02:00
|
|
|
#include "executor/nodeMergeAppend.h"
|
1999-07-16 07:00:38 +02:00
|
|
|
#include "executor/nodeMergejoin.h"
|
2009-10-10 03:43:50 +02:00
|
|
|
#include "executor/nodeModifyTable.h"
|
1998-02-13 04:26:53 +01:00
|
|
|
#include "executor/nodeNestloop.h"
|
2008-10-04 23:56:55 +02:00
|
|
|
#include "executor/nodeRecursiveunion.h"
|
1998-02-13 04:26:53 +01:00
|
|
|
#include "executor/nodeResult.h"
|
2015-05-15 20:37:10 +02:00
|
|
|
#include "executor/nodeSamplescan.h"
|
1999-07-16 07:00:38 +02:00
|
|
|
#include "executor/nodeSeqscan.h"
|
2000-10-05 21:11:39 +02:00
|
|
|
#include "executor/nodeSetOp.h"
|
1999-07-16 07:00:38 +02:00
|
|
|
#include "executor/nodeSort.h"
|
1998-02-13 04:26:53 +01:00
|
|
|
#include "executor/nodeSubplan.h"
|
2000-09-29 20:21:41 +02:00
|
|
|
#include "executor/nodeSubqueryscan.h"
|
2002-12-05 16:50:39 +01:00
|
|
|
#include "executor/nodeTidscan.h"
|
1999-07-16 07:00:38 +02:00
|
|
|
#include "executor/nodeUnique.h"
|
2006-08-02 03:59:48 +02:00
|
|
|
#include "executor/nodeValuesscan.h"
|
2008-12-28 19:54:01 +01:00
|
|
|
#include "executor/nodeWindowAgg.h"
|
2008-10-04 23:56:55 +02:00
|
|
|
#include "executor/nodeWorktablescan.h"
|
2008-10-18 00:10:30 +02:00
|
|
|
#include "nodes/nodeFuncs.h"
|
2014-11-07 23:26:02 +01:00
|
|
|
#include "nodes/relation.h"
|
2011-02-23 18:18:09 +01:00
|
|
|
#include "utils/rel.h"
|
2008-10-18 00:10:30 +02:00
|
|
|
#include "utils/syscache.h"
|
|
|
|
|
|
|
|
|
|
|
|
static bool TargetListSupportsBackwardScan(List *targetlist);
|
|
|
|
static bool IndexSupportsBackwardScan(Oid indexid);
|
1996-07-09 08:22:35 +02:00
|
|
|
|
1997-09-07 07:04:48 +02:00
|
|
|
|
2003-12-18 21:21:37 +01:00
|
|
|
/*
|
|
|
|
* ExecReScan
|
|
|
|
* Reset a plan node so that its output can be re-scanned.
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
2003-12-18 21:21:37 +01:00
|
|
|
* Note that if the plan node has parameters that have changed value,
|
|
|
|
* the output might be different from last time.
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
|
|
|
void
|
2010-07-12 19:01:06 +02:00
|
|
|
ExecReScan(PlanState *node)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
2002-12-05 16:50:39 +01:00
|
|
|
/* If collecting timing stats, update them */
|
2001-09-18 03:59:07 +02:00
|
|
|
if (node->instrument)
|
|
|
|
InstrEndLoop(node->instrument);
|
1998-02-13 04:26:53 +01:00
|
|
|
|
Fix mis-calculation of extParam/allParam sets for plan nodes, as seen in
bug #4290. The fundamental bug is that masking extParam by outer_params,
as finalize_plan had been doing, caused us to lose the information that
an initPlan depended on the output of a sibling initPlan. On reflection
the best thing to do seemed to be not to try to adjust outer_params for
this case but get rid of it entirely. The only thing it was really doing
for us was to filter out param IDs associated with SubPlan nodes, and that
can be done (with greater accuracy) while processing individual SubPlan
nodes in finalize_primnode. This approach was vindicated by the discovery
that the masking method was hiding a second bug: SS_finalize_plan failed to
remove extParam bits for initPlan output params that were referenced in the
main plan tree (it only got rid of those referenced by other initPlans).
It's not clear that this caused any real problems, given the limited use
of extParam by the executor, but it's certainly not what was intended.
I originally thought that there was also a problem with needing to include
indirect dependencies on external params in initPlans' param sets, but it
turns out that the executor handles this correctly so long as the depended-on
initPlan is earlier in the initPlans list than the one using its output.
That seems a bit of a fragile assumption, but it is true at the moment,
so I just documented it in some code comments rather than making what would
be rather invasive changes to remove the assumption.
Back-patch to 8.1. Previous versions don't have the case of initPlans
referring to other initPlans' outputs, so while the existing logic is still
questionable for them, there are not any known bugs to be fixed. So I'll
refrain from changing them for now.
2008-07-10 03:17:29 +02:00
|
|
|
/*
|
|
|
|
* If we have changed parameters, propagate that info.
|
|
|
|
*
|
|
|
|
* Note: ExecReScanSetParamPlan() can add bits to node->chgParam,
|
|
|
|
* corresponding to the output param(s) that the InitPlan will update.
|
|
|
|
* Since we make only one pass over the list, that means that an InitPlan
|
|
|
|
* can depend on the output param(s) of a sibling InitPlan only if that
|
|
|
|
* sibling appears earlier in the list. This is workable for now given
|
|
|
|
* the limited ways in which one InitPlan could depend on another, but
|
|
|
|
* eventually we might need to work harder (or else make the planner
|
|
|
|
* enlarge the extParam/allParam sets to include the params of depended-on
|
|
|
|
* InitPlans).
|
|
|
|
*/
|
2003-02-09 01:30:41 +01:00
|
|
|
if (node->chgParam != NULL)
|
1998-02-13 04:26:53 +01:00
|
|
|
{
|
2004-08-29 07:07:03 +02:00
|
|
|
ListCell *l;
|
1998-02-26 05:46:47 +01:00
|
|
|
|
2004-05-26 06:41:50 +02:00
|
|
|
foreach(l, node->initPlan)
|
1998-02-13 04:26:53 +01:00
|
|
|
{
|
2004-05-26 06:41:50 +02:00
|
|
|
SubPlanState *sstate = (SubPlanState *) lfirst(l);
|
2002-12-13 20:46:01 +01:00
|
|
|
PlanState *splan = sstate->planstate;
|
1998-02-26 05:46:47 +01:00
|
|
|
|
2003-02-09 01:30:41 +01:00
|
|
|
if (splan->plan->extParam != NULL) /* don't care about child
|
|
|
|
* local Params */
|
|
|
|
UpdateChangedParamSet(splan, node->chgParam);
|
|
|
|
if (splan->chgParam != NULL)
|
2002-12-13 20:46:01 +01:00
|
|
|
ExecReScanSetParamPlan(sstate, node);
|
1998-02-13 04:26:53 +01:00
|
|
|
}
|
2004-05-26 06:41:50 +02:00
|
|
|
foreach(l, node->subPlan)
|
1998-02-13 04:26:53 +01:00
|
|
|
{
|
2004-05-26 06:41:50 +02:00
|
|
|
SubPlanState *sstate = (SubPlanState *) lfirst(l);
|
2002-12-13 20:46:01 +01:00
|
|
|
PlanState *splan = sstate->planstate;
|
1998-02-26 05:46:47 +01:00
|
|
|
|
2003-02-09 01:30:41 +01:00
|
|
|
if (splan->plan->extParam != NULL)
|
|
|
|
UpdateChangedParamSet(splan, node->chgParam);
|
1998-02-13 04:26:53 +01:00
|
|
|
}
|
|
|
|
/* Well. Now set chgParam for left/right trees. */
|
1998-02-26 05:46:47 +01:00
|
|
|
if (node->lefttree != NULL)
|
2003-02-09 01:30:41 +01:00
|
|
|
UpdateChangedParamSet(node->lefttree, node->chgParam);
|
1998-02-26 05:46:47 +01:00
|
|
|
if (node->righttree != NULL)
|
2003-02-09 01:30:41 +01:00
|
|
|
UpdateChangedParamSet(node->righttree, node->chgParam);
|
1998-02-13 04:26:53 +01:00
|
|
|
}
|
|
|
|
|
2003-12-18 21:21:37 +01:00
|
|
|
/* Shut down any SRFs in the plan node's targetlist */
|
|
|
|
if (node->ps_ExprContext)
|
|
|
|
ReScanExprContext(node->ps_ExprContext);
|
|
|
|
|
|
|
|
/* And do node-type-specific processing */
|
1997-09-07 07:04:48 +02:00
|
|
|
switch (nodeTag(node))
|
|
|
|
{
|
2002-12-05 16:50:39 +01:00
|
|
|
case T_ResultState:
|
2010-07-12 19:01:06 +02:00
|
|
|
ExecReScanResult((ResultState *) node);
|
1998-02-13 04:26:53 +01:00
|
|
|
break;
|
1997-09-08 04:41:22 +02:00
|
|
|
|
2009-10-10 03:43:50 +02:00
|
|
|
case T_ModifyTableState:
|
2010-07-12 19:01:06 +02:00
|
|
|
ExecReScanModifyTable((ModifyTableState *) node);
|
2009-10-10 03:43:50 +02:00
|
|
|
break;
|
|
|
|
|
2002-12-05 16:50:39 +01:00
|
|
|
case T_AppendState:
|
2010-07-12 19:01:06 +02:00
|
|
|
ExecReScanAppend((AppendState *) node);
|
1998-02-13 04:26:53 +01:00
|
|
|
break;
|
1997-09-08 04:41:22 +02:00
|
|
|
|
2010-10-14 22:56:39 +02:00
|
|
|
case T_MergeAppendState:
|
|
|
|
ExecReScanMergeAppend((MergeAppendState *) node);
|
|
|
|
break;
|
|
|
|
|
2008-10-04 23:56:55 +02:00
|
|
|
case T_RecursiveUnionState:
|
2010-07-12 19:01:06 +02:00
|
|
|
ExecReScanRecursiveUnion((RecursiveUnionState *) node);
|
2008-10-04 23:56:55 +02:00
|
|
|
break;
|
|
|
|
|
2005-04-20 00:35:18 +02:00
|
|
|
case T_BitmapAndState:
|
2010-07-12 19:01:06 +02:00
|
|
|
ExecReScanBitmapAnd((BitmapAndState *) node);
|
2005-04-20 00:35:18 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case T_BitmapOrState:
|
2010-07-12 19:01:06 +02:00
|
|
|
ExecReScanBitmapOr((BitmapOrState *) node);
|
2005-04-20 00:35:18 +02:00
|
|
|
break;
|
|
|
|
|
2002-12-05 16:50:39 +01:00
|
|
|
case T_SeqScanState:
|
2010-07-12 19:01:06 +02:00
|
|
|
ExecReScanSeqScan((SeqScanState *) node);
|
2000-09-29 20:21:41 +02:00
|
|
|
break;
|
|
|
|
|
2015-05-15 20:37:10 +02:00
|
|
|
case T_SampleScanState:
|
|
|
|
ExecReScanSampleScan((SampleScanState *) node);
|
|
|
|
break;
|
|
|
|
|
Add a Gather executor node.
A Gather executor node runs any number of copies of a plan in an equal
number of workers and merges all of the results into a single tuple
stream. It can also run the plan itself, if the workers are
unavailable or haven't started up yet. It is intended to work with
the Partial Seq Scan node which will be added in future commits.
It could also be used to implement parallel query of a different sort
by itself, without help from Partial Seq Scan, if the single_copy mode
is used. In that mode, a worker executes the plan, and the parallel
leader does not, merely collecting the worker's results. So, a Gather
node could be inserted into a plan to split the execution of that plan
across two processes. Nested Gather nodes aren't currently supported,
but we might want to add support for that in the future.
There's nothing in the planner to actually generate Gather nodes yet,
so it's not quite time to break out the champagne. But we're getting
close.
Amit Kapila. Some designs suggestions were provided by me, and I also
reviewed the patch. Single-copy mode, documentation, and other minor
changes also by me.
2015-10-01 01:23:36 +02:00
|
|
|
case T_GatherState:
|
|
|
|
ExecReScanGather((GatherState *) node);
|
|
|
|
break;
|
|
|
|
|
2002-12-05 16:50:39 +01:00
|
|
|
case T_IndexScanState:
|
2010-07-12 19:01:06 +02:00
|
|
|
ExecReScanIndexScan((IndexScanState *) node);
|
2000-09-29 20:21:41 +02:00
|
|
|
break;
|
|
|
|
|
2011-10-11 20:20:06 +02:00
|
|
|
case T_IndexOnlyScanState:
|
|
|
|
ExecReScanIndexOnlyScan((IndexOnlyScanState *) node);
|
|
|
|
break;
|
|
|
|
|
2005-04-20 00:35:18 +02:00
|
|
|
case T_BitmapIndexScanState:
|
2010-07-12 19:01:06 +02:00
|
|
|
ExecReScanBitmapIndexScan((BitmapIndexScanState *) node);
|
2005-04-20 00:35:18 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case T_BitmapHeapScanState:
|
2010-07-12 19:01:06 +02:00
|
|
|
ExecReScanBitmapHeapScan((BitmapHeapScanState *) node);
|
2005-04-20 00:35:18 +02:00
|
|
|
break;
|
|
|
|
|
2002-12-05 16:50:39 +01:00
|
|
|
case T_TidScanState:
|
2010-07-12 19:01:06 +02:00
|
|
|
ExecReScanTidScan((TidScanState *) node);
|
2002-05-12 22:10:05 +02:00
|
|
|
break;
|
|
|
|
|
2002-12-05 16:50:39 +01:00
|
|
|
case T_SubqueryScanState:
|
2010-07-12 19:01:06 +02:00
|
|
|
ExecReScanSubqueryScan((SubqueryScanState *) node);
|
1998-02-13 04:26:53 +01:00
|
|
|
break;
|
1997-09-08 04:41:22 +02:00
|
|
|
|
2002-12-05 16:50:39 +01:00
|
|
|
case T_FunctionScanState:
|
2010-07-12 19:01:06 +02:00
|
|
|
ExecReScanFunctionScan((FunctionScanState *) node);
|
1998-02-13 04:26:53 +01:00
|
|
|
break;
|
|
|
|
|
2006-08-02 03:59:48 +02:00
|
|
|
case T_ValuesScanState:
|
2010-07-12 19:01:06 +02:00
|
|
|
ExecReScanValuesScan((ValuesScanState *) node);
|
2006-08-02 03:59:48 +02:00
|
|
|
break;
|
|
|
|
|
2008-10-04 23:56:55 +02:00
|
|
|
case T_CteScanState:
|
2010-07-12 19:01:06 +02:00
|
|
|
ExecReScanCteScan((CteScanState *) node);
|
2008-10-04 23:56:55 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case T_WorkTableScanState:
|
2010-07-12 19:01:06 +02:00
|
|
|
ExecReScanWorkTableScan((WorkTableScanState *) node);
|
2008-10-04 23:56:55 +02:00
|
|
|
break;
|
|
|
|
|
2011-02-20 06:17:18 +01:00
|
|
|
case T_ForeignScanState:
|
|
|
|
ExecReScanForeignScan((ForeignScanState *) node);
|
|
|
|
break;
|
|
|
|
|
2014-11-07 23:26:02 +01:00
|
|
|
case T_CustomScanState:
|
|
|
|
ExecReScanCustomScan((CustomScanState *) node);
|
|
|
|
break;
|
|
|
|
|
2002-12-05 16:50:39 +01:00
|
|
|
case T_NestLoopState:
|
2010-07-12 19:01:06 +02:00
|
|
|
ExecReScanNestLoop((NestLoopState *) node);
|
1998-02-13 04:26:53 +01:00
|
|
|
break;
|
|
|
|
|
2002-12-05 16:50:39 +01:00
|
|
|
case T_MergeJoinState:
|
2010-07-12 19:01:06 +02:00
|
|
|
ExecReScanMergeJoin((MergeJoinState *) node);
|
1998-02-13 04:26:53 +01:00
|
|
|
break;
|
|
|
|
|
2002-12-05 16:50:39 +01:00
|
|
|
case T_HashJoinState:
|
2010-07-12 19:01:06 +02:00
|
|
|
ExecReScanHashJoin((HashJoinState *) node);
|
1998-02-13 04:26:53 +01:00
|
|
|
break;
|
1997-09-08 04:41:22 +02:00
|
|
|
|
2002-12-05 16:50:39 +01:00
|
|
|
case T_MaterialState:
|
2010-07-12 19:01:06 +02:00
|
|
|
ExecReScanMaterial((MaterialState *) node);
|
1998-07-16 03:49:19 +02:00
|
|
|
break;
|
|
|
|
|
2002-12-05 16:50:39 +01:00
|
|
|
case T_SortState:
|
2010-07-12 19:01:06 +02:00
|
|
|
ExecReScanSort((SortState *) node);
|
1998-02-13 04:26:53 +01:00
|
|
|
break;
|
|
|
|
|
2002-12-05 16:50:39 +01:00
|
|
|
case T_GroupState:
|
2010-07-12 19:01:06 +02:00
|
|
|
ExecReScanGroup((GroupState *) node);
|
1998-02-23 07:28:16 +01:00
|
|
|
break;
|
|
|
|
|
2002-12-05 16:50:39 +01:00
|
|
|
case T_AggState:
|
2010-07-12 19:01:06 +02:00
|
|
|
ExecReScanAgg((AggState *) node);
|
2000-10-05 21:11:39 +02:00
|
|
|
break;
|
|
|
|
|
2008-12-28 19:54:01 +01:00
|
|
|
case T_WindowAggState:
|
2010-07-12 19:01:06 +02:00
|
|
|
ExecReScanWindowAgg((WindowAggState *) node);
|
2008-12-28 19:54:01 +01:00
|
|
|
break;
|
|
|
|
|
2002-12-05 16:50:39 +01:00
|
|
|
case T_UniqueState:
|
2010-07-12 19:01:06 +02:00
|
|
|
ExecReScanUnique((UniqueState *) node);
|
2000-10-26 23:38:24 +02:00
|
|
|
break;
|
|
|
|
|
2002-12-05 16:50:39 +01:00
|
|
|
case T_HashState:
|
2010-07-12 19:01:06 +02:00
|
|
|
ExecReScanHash((HashState *) node);
|
1998-02-23 07:28:16 +01:00
|
|
|
break;
|
|
|
|
|
2002-12-05 16:50:39 +01:00
|
|
|
case T_SetOpState:
|
2010-07-12 19:01:06 +02:00
|
|
|
ExecReScanSetOp((SetOpState *) node);
|
1998-02-27 17:11:28 +01:00
|
|
|
break;
|
|
|
|
|
2009-10-12 20:10:51 +02:00
|
|
|
case T_LockRowsState:
|
2010-07-12 19:01:06 +02:00
|
|
|
ExecReScanLockRows((LockRowsState *) node);
|
2009-10-12 20:10:51 +02:00
|
|
|
break;
|
|
|
|
|
2002-12-05 16:50:39 +01:00
|
|
|
case T_LimitState:
|
2010-07-12 19:01:06 +02:00
|
|
|
ExecReScanLimit((LimitState *) node);
|
1998-07-16 00:16:21 +02:00
|
|
|
break;
|
|
|
|
|
1997-09-08 04:41:22 +02:00
|
|
|
default:
|
2003-07-21 19:05:12 +02:00
|
|
|
elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node));
|
|
|
|
break;
|
1997-09-07 07:04:48 +02:00
|
|
|
}
|
1998-02-26 05:46:47 +01:00
|
|
|
|
2003-02-09 01:30:41 +01:00
|
|
|
if (node->chgParam != NULL)
|
1998-02-13 04:26:53 +01:00
|
|
|
{
|
2003-02-09 01:30:41 +01:00
|
|
|
bms_free(node->chgParam);
|
|
|
|
node->chgParam = NULL;
|
1998-02-13 04:26:53 +01:00
|
|
|
}
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
1997-09-07 07:04:48 +02:00
|
|
|
|
2002-11-30 06:21:03 +01:00
|
|
|
/*
|
|
|
|
* ExecMarkPos
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
2002-11-30 06:21:03 +01:00
|
|
|
* Marks the current scan position.
|
2014-11-21 02:20:54 +01:00
|
|
|
*
|
|
|
|
* NOTE: mark/restore capability is currently needed only for plan nodes
|
|
|
|
* that are the immediate inner child of a MergeJoin node. Since MergeJoin
|
|
|
|
* requires sorted input, there is never any need to support mark/restore in
|
|
|
|
* node types that cannot produce sorted output. There are some cases in
|
|
|
|
* which a node can pass through sorted data from its child; if we don't
|
|
|
|
* implement mark/restore for such a node type, the planner compensates by
|
|
|
|
* inserting a Material node above that node.
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
|
|
|
void
|
2003-08-08 23:42:59 +02:00
|
|
|
ExecMarkPos(PlanState *node)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
1997-09-07 07:04:48 +02:00
|
|
|
switch (nodeTag(node))
|
|
|
|
{
|
2002-12-05 16:50:39 +01:00
|
|
|
case T_IndexScanState:
|
|
|
|
ExecIndexMarkPos((IndexScanState *) node);
|
1997-09-08 04:41:22 +02:00
|
|
|
break;
|
1997-09-07 07:04:48 +02:00
|
|
|
|
2011-10-11 20:20:06 +02:00
|
|
|
case T_IndexOnlyScanState:
|
|
|
|
ExecIndexOnlyMarkPos((IndexOnlyScanState *) node);
|
|
|
|
break;
|
|
|
|
|
2014-11-07 23:26:02 +01:00
|
|
|
case T_CustomScanState:
|
|
|
|
ExecCustomMarkPos((CustomScanState *) node);
|
|
|
|
break;
|
|
|
|
|
2002-12-05 16:50:39 +01:00
|
|
|
case T_MaterialState:
|
|
|
|
ExecMaterialMarkPos((MaterialState *) node);
|
2000-06-19 00:44:35 +02:00
|
|
|
break;
|
|
|
|
|
2002-12-05 16:50:39 +01:00
|
|
|
case T_SortState:
|
|
|
|
ExecSortMarkPos((SortState *) node);
|
1997-09-08 04:41:22 +02:00
|
|
|
break;
|
1997-09-07 07:04:48 +02:00
|
|
|
|
2007-02-15 04:07:13 +01:00
|
|
|
case T_ResultState:
|
|
|
|
ExecResultMarkPos((ResultState *) node);
|
|
|
|
break;
|
|
|
|
|
1997-09-08 04:41:22 +02:00
|
|
|
default:
|
2000-07-26 01:43:38 +02:00
|
|
|
/* don't make hard error unless caller asks to restore... */
|
2003-07-21 19:05:12 +02:00
|
|
|
elog(DEBUG2, "unrecognized node type: %d", (int) nodeTag(node));
|
1997-09-08 04:41:22 +02:00
|
|
|
break;
|
1997-09-07 07:04:48 +02:00
|
|
|
}
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
1997-09-07 07:04:48 +02:00
|
|
|
|
2002-11-30 06:21:03 +01:00
|
|
|
/*
|
|
|
|
* ExecRestrPos
|
2000-07-26 01:43:38 +02:00
|
|
|
*
|
2002-11-30 06:21:03 +01:00
|
|
|
* restores the scan position previously saved with ExecMarkPos()
|
2005-05-15 23:19:55 +02:00
|
|
|
*
|
|
|
|
* NOTE: the semantics of this are that the first ExecProcNode following
|
|
|
|
* the restore operation will yield the same tuple as the first one following
|
2014-05-06 18:12:18 +02:00
|
|
|
* the mark operation. It is unspecified what happens to the plan node's
|
2005-05-15 23:19:55 +02:00
|
|
|
* result TupleTableSlot. (In most cases the result slot is unchanged by
|
|
|
|
* a restore, but the node may choose to clear it or to load it with the
|
2005-10-15 04:49:52 +02:00
|
|
|
* restored-to tuple.) Hence the caller should discard any previously
|
2005-05-15 23:19:55 +02:00
|
|
|
* returned TupleTableSlot after doing a restore.
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
|
|
|
void
|
2003-08-08 23:42:59 +02:00
|
|
|
ExecRestrPos(PlanState *node)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
1997-09-07 07:04:48 +02:00
|
|
|
switch (nodeTag(node))
|
|
|
|
{
|
2002-12-05 16:50:39 +01:00
|
|
|
case T_IndexScanState:
|
|
|
|
ExecIndexRestrPos((IndexScanState *) node);
|
2000-07-26 01:43:38 +02:00
|
|
|
break;
|
1997-09-07 07:04:48 +02:00
|
|
|
|
2011-10-11 20:20:06 +02:00
|
|
|
case T_IndexOnlyScanState:
|
|
|
|
ExecIndexOnlyRestrPos((IndexOnlyScanState *) node);
|
|
|
|
break;
|
|
|
|
|
2014-11-07 23:26:02 +01:00
|
|
|
case T_CustomScanState:
|
|
|
|
ExecCustomRestrPos((CustomScanState *) node);
|
|
|
|
break;
|
|
|
|
|
2002-12-05 16:50:39 +01:00
|
|
|
case T_MaterialState:
|
|
|
|
ExecMaterialRestrPos((MaterialState *) node);
|
2000-07-26 01:43:38 +02:00
|
|
|
break;
|
2000-06-19 00:44:35 +02:00
|
|
|
|
2002-12-05 16:50:39 +01:00
|
|
|
case T_SortState:
|
|
|
|
ExecSortRestrPos((SortState *) node);
|
2000-07-26 01:43:38 +02:00
|
|
|
break;
|
1997-09-07 07:04:48 +02:00
|
|
|
|
2007-02-15 04:07:13 +01:00
|
|
|
case T_ResultState:
|
|
|
|
ExecResultRestrPos((ResultState *) node);
|
|
|
|
break;
|
|
|
|
|
1997-09-08 04:41:22 +02:00
|
|
|
default:
|
2003-07-21 19:05:12 +02:00
|
|
|
elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node));
|
2000-07-26 01:43:38 +02:00
|
|
|
break;
|
1997-09-07 07:04:48 +02:00
|
|
|
}
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
2002-11-30 06:21:03 +01:00
|
|
|
|
|
|
|
/*
|
2014-11-21 00:36:07 +01:00
|
|
|
* ExecSupportsMarkRestore - does a Path support mark/restore?
|
|
|
|
*
|
|
|
|
* This is used during planning and so must accept a Path, not a Plan.
|
|
|
|
* We keep it here to be adjacent to the routines above, which also must
|
|
|
|
* know which plan types support mark/restore.
|
2002-11-30 06:21:03 +01:00
|
|
|
*/
|
|
|
|
bool
|
2014-11-07 23:26:02 +01:00
|
|
|
ExecSupportsMarkRestore(Path *pathnode)
|
2002-11-30 06:21:03 +01:00
|
|
|
{
|
2014-11-21 00:36:07 +01:00
|
|
|
/*
|
|
|
|
* For consistency with the routines above, we do not examine the nodeTag
|
|
|
|
* but rather the pathtype, which is the Plan node type the Path would
|
|
|
|
* produce.
|
|
|
|
*/
|
2014-11-07 23:26:02 +01:00
|
|
|
switch (pathnode->pathtype)
|
2002-11-30 06:21:03 +01:00
|
|
|
{
|
|
|
|
case T_IndexScan:
|
2011-10-11 20:20:06 +02:00
|
|
|
case T_IndexOnlyScan:
|
2002-11-30 06:21:03 +01:00
|
|
|
case T_Material:
|
|
|
|
case T_Sort:
|
|
|
|
return true;
|
|
|
|
|
2014-11-21 00:36:07 +01:00
|
|
|
case T_CustomScan:
|
|
|
|
Assert(IsA(pathnode, CustomPath));
|
|
|
|
if (((CustomPath *) pathnode)->flags & CUSTOMPATH_SUPPORT_MARK_RESTORE)
|
|
|
|
return true;
|
|
|
|
return false;
|
|
|
|
|
2007-02-15 04:07:13 +01:00
|
|
|
case T_Result:
|
2007-11-15 22:14:46 +01:00
|
|
|
|
2007-02-15 04:07:13 +01:00
|
|
|
/*
|
2014-11-21 00:36:07 +01:00
|
|
|
* Although Result supports mark/restore if it has a child plan
|
|
|
|
* that does, we presently come here only for ResultPath nodes,
|
|
|
|
* which represent Result plans without a child plan. So there is
|
2014-11-21 02:20:54 +01:00
|
|
|
* nothing to recurse to and we can just say "false". (This means
|
2015-05-24 03:35:49 +02:00
|
|
|
* that Result's support for mark/restore is in fact dead code. We
|
|
|
|
* keep it since it's not much code, and someday the planner might
|
|
|
|
* be smart enough to use it. That would require making this
|
|
|
|
* function smarter too, of course.)
|
2007-02-15 04:07:13 +01:00
|
|
|
*/
|
2014-11-21 00:36:07 +01:00
|
|
|
Assert(IsA(pathnode, ResultPath));
|
2007-02-15 04:07:13 +01:00
|
|
|
return false;
|
|
|
|
|
2002-11-30 06:21:03 +01:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
2003-03-10 04:53:52 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
* 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;
|
|
|
|
|
2015-11-11 14:57:52 +01:00
|
|
|
/*
|
|
|
|
* Parallel-aware nodes return a subset of the tuples in each worker,
|
|
|
|
* and in general we can't expect to have enough bookkeeping state to
|
|
|
|
* know which ones we returned in this worker as opposed to some other
|
|
|
|
* worker.
|
|
|
|
*/
|
|
|
|
if (node->parallel_aware)
|
|
|
|
return false;
|
|
|
|
|
2003-03-10 04:53:52 +01:00
|
|
|
switch (nodeTag(node))
|
|
|
|
{
|
|
|
|
case T_Result:
|
|
|
|
if (outerPlan(node) != NULL)
|
2008-10-18 00:10:30 +02:00
|
|
|
return ExecSupportsBackwardScan(outerPlan(node)) &&
|
|
|
|
TargetListSupportsBackwardScan(node->targetlist);
|
2003-03-10 04:53:52 +01:00
|
|
|
else
|
|
|
|
return false;
|
|
|
|
|
|
|
|
case T_Append:
|
|
|
|
{
|
2004-05-26 06:41:50 +02:00
|
|
|
ListCell *l;
|
2003-08-04 02:43:34 +02:00
|
|
|
|
|
|
|
foreach(l, ((Append *) node)->appendplans)
|
|
|
|
{
|
|
|
|
if (!ExecSupportsBackwardScan((Plan *) lfirst(l)))
|
|
|
|
return false;
|
|
|
|
}
|
2008-10-18 00:10:30 +02:00
|
|
|
/* need not check tlist because Append doesn't evaluate it */
|
2003-08-04 02:43:34 +02:00
|
|
|
return true;
|
2003-03-10 04:53:52 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
case T_SeqScan:
|
|
|
|
case T_TidScan:
|
|
|
|
case T_FunctionScan:
|
2006-08-02 03:59:48 +02:00
|
|
|
case T_ValuesScan:
|
2008-10-04 23:56:55 +02:00
|
|
|
case T_CteScan:
|
2008-10-18 00:10:30 +02:00
|
|
|
return TargetListSupportsBackwardScan(node->targetlist);
|
|
|
|
|
Redesign tablesample method API, and do extensive code review.
The original implementation of TABLESAMPLE modeled the tablesample method
API on index access methods, which wasn't a good choice because, without
specialized DDL commands, there's no way to build an extension that can
implement a TSM. (Raw inserts into system catalogs are not an acceptable
thing to do, because we can't undo them during DROP EXTENSION, nor will
pg_upgrade behave sanely.) Instead adopt an API more like procedural
language handlers or foreign data wrappers, wherein the only SQL-level
support object needed is a single handler function identified by having
a special return type. This lets us get rid of the supporting catalog
altogether, so that no custom DDL support is needed for the feature.
Adjust the API so that it can support non-constant tablesample arguments
(the original coding assumed we could evaluate the argument expressions at
ExecInitSampleScan time, which is undesirable even if it weren't outright
unsafe), and discourage sampling methods from looking at invisible tuples.
Make sure that the BERNOULLI and SYSTEM methods are genuinely repeatable
within and across queries, as required by the SQL standard, and deal more
honestly with methods that can't support that requirement.
Make a full code-review pass over the tablesample additions, and fix
assorted bugs, omissions, infelicities, and cosmetic issues (such as
failure to put the added code stanzas in a consistent ordering).
Improve EXPLAIN's output of tablesample plans, too.
Back-patch to 9.5 so that we don't have to support the original API
in production.
2015-07-25 20:39:00 +02:00
|
|
|
case T_SampleScan:
|
|
|
|
/* Simplify life for tablesample methods by disallowing this */
|
|
|
|
return false;
|
|
|
|
|
Add a Gather executor node.
A Gather executor node runs any number of copies of a plan in an equal
number of workers and merges all of the results into a single tuple
stream. It can also run the plan itself, if the workers are
unavailable or haven't started up yet. It is intended to work with
the Partial Seq Scan node which will be added in future commits.
It could also be used to implement parallel query of a different sort
by itself, without help from Partial Seq Scan, if the single_copy mode
is used. In that mode, a worker executes the plan, and the parallel
leader does not, merely collecting the worker's results. So, a Gather
node could be inserted into a plan to split the execution of that plan
across two processes. Nested Gather nodes aren't currently supported,
but we might want to add support for that in the future.
There's nothing in the planner to actually generate Gather nodes yet,
so it's not quite time to break out the champagne. But we're getting
close.
Amit Kapila. Some designs suggestions were provided by me, and I also
reviewed the patch. Single-copy mode, documentation, and other minor
changes also by me.
2015-10-01 01:23:36 +02:00
|
|
|
case T_Gather:
|
|
|
|
return false;
|
|
|
|
|
2008-10-18 00:10:30 +02:00
|
|
|
case T_IndexScan:
|
|
|
|
return IndexSupportsBackwardScan(((IndexScan *) node)->indexid) &&
|
|
|
|
TargetListSupportsBackwardScan(node->targetlist);
|
2003-03-10 04:53:52 +01:00
|
|
|
|
2011-10-11 20:20:06 +02:00
|
|
|
case T_IndexOnlyScan:
|
|
|
|
return IndexSupportsBackwardScan(((IndexOnlyScan *) node)->indexid) &&
|
|
|
|
TargetListSupportsBackwardScan(node->targetlist);
|
|
|
|
|
2003-03-10 04:53:52 +01:00
|
|
|
case T_SubqueryScan:
|
2008-10-18 00:10:30 +02:00
|
|
|
return ExecSupportsBackwardScan(((SubqueryScan *) node)->subplan) &&
|
|
|
|
TargetListSupportsBackwardScan(node->targetlist);
|
2003-03-10 04:53:52 +01:00
|
|
|
|
2014-11-07 23:26:02 +01:00
|
|
|
case T_CustomScan:
|
|
|
|
{
|
2014-11-21 00:36:07 +01:00
|
|
|
uint32 flags = ((CustomScan *) node)->flags;
|
2014-11-07 23:26:02 +01:00
|
|
|
|
2014-11-21 00:36:07 +01:00
|
|
|
if ((flags & CUSTOMPATH_SUPPORT_BACKWARD_SCAN) &&
|
|
|
|
TargetListSupportsBackwardScan(node->targetlist))
|
2014-11-07 23:26:02 +01:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
|
2003-03-10 04:53:52 +01:00
|
|
|
case T_Material:
|
|
|
|
case T_Sort:
|
2008-10-18 00:10:30 +02:00
|
|
|
/* these don't evaluate tlist */
|
2003-03-10 04:53:52 +01:00
|
|
|
return true;
|
|
|
|
|
2009-10-12 20:10:51 +02:00
|
|
|
case T_LockRows:
|
2003-03-10 04:53:52 +01:00
|
|
|
case T_Limit:
|
2009-10-12 20:10:51 +02:00
|
|
|
/* these don't evaluate tlist */
|
2003-03-10 04:53:52 +01:00
|
|
|
return ExecSupportsBackwardScan(outerPlan(node));
|
|
|
|
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
2008-10-18 00:10:30 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* If the tlist contains set-returning functions, we can't support backward
|
|
|
|
* scan, because the TupFromTlist code is direction-ignorant.
|
|
|
|
*/
|
|
|
|
static bool
|
|
|
|
TargetListSupportsBackwardScan(List *targetlist)
|
|
|
|
{
|
|
|
|
if (expression_returns_set((Node *) targetlist))
|
|
|
|
return false;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2011-10-11 20:20:06 +02:00
|
|
|
* An IndexScan or IndexOnlyScan node supports backward scan only if the
|
|
|
|
* index's AM does.
|
2008-10-18 00:10:30 +02:00
|
|
|
*/
|
|
|
|
static bool
|
|
|
|
IndexSupportsBackwardScan(Oid indexid)
|
|
|
|
{
|
|
|
|
bool result;
|
|
|
|
HeapTuple ht_idxrel;
|
|
|
|
HeapTuple ht_am;
|
|
|
|
Form_pg_class idxrelrec;
|
|
|
|
Form_pg_am amrec;
|
|
|
|
|
|
|
|
/* Fetch the pg_class tuple of the index relation */
|
2010-02-14 19:42:19 +01:00
|
|
|
ht_idxrel = SearchSysCache1(RELOID, ObjectIdGetDatum(indexid));
|
2008-10-18 00:10:30 +02:00
|
|
|
if (!HeapTupleIsValid(ht_idxrel))
|
|
|
|
elog(ERROR, "cache lookup failed for relation %u", indexid);
|
|
|
|
idxrelrec = (Form_pg_class) GETSTRUCT(ht_idxrel);
|
|
|
|
|
|
|
|
/* Fetch the pg_am tuple of the index' access method */
|
2010-02-14 19:42:19 +01:00
|
|
|
ht_am = SearchSysCache1(AMOID, ObjectIdGetDatum(idxrelrec->relam));
|
2008-10-18 00:10:30 +02:00
|
|
|
if (!HeapTupleIsValid(ht_am))
|
|
|
|
elog(ERROR, "cache lookup failed for access method %u",
|
|
|
|
idxrelrec->relam);
|
|
|
|
amrec = (Form_pg_am) GETSTRUCT(ht_am);
|
|
|
|
|
|
|
|
result = amrec->amcanbackward;
|
|
|
|
|
|
|
|
ReleaseSysCache(ht_idxrel);
|
|
|
|
ReleaseSysCache(ht_am);
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
2009-09-13 00:12:09 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* ExecMaterializesOutput - does a plan type materialize its output?
|
|
|
|
*
|
|
|
|
* Returns true if the plan node type is one that automatically materializes
|
|
|
|
* its output (typically by keeping it in a tuplestore). For such plans,
|
|
|
|
* a rescan without any parameter change will have zero startup cost and
|
|
|
|
* very low per-tuple cost.
|
|
|
|
*/
|
|
|
|
bool
|
|
|
|
ExecMaterializesOutput(NodeTag plantype)
|
|
|
|
{
|
|
|
|
switch (plantype)
|
|
|
|
{
|
|
|
|
case T_Material:
|
|
|
|
case T_FunctionScan:
|
|
|
|
case T_CteScan:
|
|
|
|
case T_WorkTableScan:
|
|
|
|
case T_Sort:
|
|
|
|
return true;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|