Header And Logo

PostgreSQL
| The world's most advanced open source database.

execAmi.c

Go to the documentation of this file.
00001 /*-------------------------------------------------------------------------
00002  *
00003  * execAmi.c
00004  *    miscellaneous executor access method routines
00005  *
00006  * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
00007  * Portions Copyright (c) 1994, Regents of the University of California
00008  *
00009  *  src/backend/executor/execAmi.c
00010  *
00011  *-------------------------------------------------------------------------
00012  */
00013 #include "postgres.h"
00014 
00015 #include "access/htup_details.h"
00016 #include "executor/execdebug.h"
00017 #include "executor/nodeAgg.h"
00018 #include "executor/nodeAppend.h"
00019 #include "executor/nodeBitmapAnd.h"
00020 #include "executor/nodeBitmapHeapscan.h"
00021 #include "executor/nodeBitmapIndexscan.h"
00022 #include "executor/nodeBitmapOr.h"
00023 #include "executor/nodeCtescan.h"
00024 #include "executor/nodeForeignscan.h"
00025 #include "executor/nodeFunctionscan.h"
00026 #include "executor/nodeGroup.h"
00027 #include "executor/nodeGroup.h"
00028 #include "executor/nodeHash.h"
00029 #include "executor/nodeHashjoin.h"
00030 #include "executor/nodeIndexonlyscan.h"
00031 #include "executor/nodeIndexscan.h"
00032 #include "executor/nodeLimit.h"
00033 #include "executor/nodeLockRows.h"
00034 #include "executor/nodeMaterial.h"
00035 #include "executor/nodeMergeAppend.h"
00036 #include "executor/nodeMergejoin.h"
00037 #include "executor/nodeModifyTable.h"
00038 #include "executor/nodeNestloop.h"
00039 #include "executor/nodeRecursiveunion.h"
00040 #include "executor/nodeResult.h"
00041 #include "executor/nodeSeqscan.h"
00042 #include "executor/nodeSetOp.h"
00043 #include "executor/nodeSort.h"
00044 #include "executor/nodeSubplan.h"
00045 #include "executor/nodeSubqueryscan.h"
00046 #include "executor/nodeTidscan.h"
00047 #include "executor/nodeUnique.h"
00048 #include "executor/nodeValuesscan.h"
00049 #include "executor/nodeWindowAgg.h"
00050 #include "executor/nodeWorktablescan.h"
00051 #include "nodes/nodeFuncs.h"
00052 #include "utils/rel.h"
00053 #include "utils/syscache.h"
00054 
00055 
00056 static bool TargetListSupportsBackwardScan(List *targetlist);
00057 static bool IndexSupportsBackwardScan(Oid indexid);
00058 
00059 
00060 /*
00061  * ExecReScan
00062  *      Reset a plan node so that its output can be re-scanned.
00063  *
00064  * Note that if the plan node has parameters that have changed value,
00065  * the output might be different from last time.
00066  */
00067 void
00068 ExecReScan(PlanState *node)
00069 {
00070     /* If collecting timing stats, update them */
00071     if (node->instrument)
00072         InstrEndLoop(node->instrument);
00073 
00074     /*
00075      * If we have changed parameters, propagate that info.
00076      *
00077      * Note: ExecReScanSetParamPlan() can add bits to node->chgParam,
00078      * corresponding to the output param(s) that the InitPlan will update.
00079      * Since we make only one pass over the list, that means that an InitPlan
00080      * can depend on the output param(s) of a sibling InitPlan only if that
00081      * sibling appears earlier in the list.  This is workable for now given
00082      * the limited ways in which one InitPlan could depend on another, but
00083      * eventually we might need to work harder (or else make the planner
00084      * enlarge the extParam/allParam sets to include the params of depended-on
00085      * InitPlans).
00086      */
00087     if (node->chgParam != NULL)
00088     {
00089         ListCell   *l;
00090 
00091         foreach(l, node->initPlan)
00092         {
00093             SubPlanState *sstate = (SubPlanState *) lfirst(l);
00094             PlanState  *splan = sstate->planstate;
00095 
00096             if (splan->plan->extParam != NULL)  /* don't care about child
00097                                                  * local Params */
00098                 UpdateChangedParamSet(splan, node->chgParam);
00099             if (splan->chgParam != NULL)
00100                 ExecReScanSetParamPlan(sstate, node);
00101         }
00102         foreach(l, node->subPlan)
00103         {
00104             SubPlanState *sstate = (SubPlanState *) lfirst(l);
00105             PlanState  *splan = sstate->planstate;
00106 
00107             if (splan->plan->extParam != NULL)
00108                 UpdateChangedParamSet(splan, node->chgParam);
00109         }
00110         /* Well. Now set chgParam for left/right trees. */
00111         if (node->lefttree != NULL)
00112             UpdateChangedParamSet(node->lefttree, node->chgParam);
00113         if (node->righttree != NULL)
00114             UpdateChangedParamSet(node->righttree, node->chgParam);
00115     }
00116 
00117     /* Shut down any SRFs in the plan node's targetlist */
00118     if (node->ps_ExprContext)
00119         ReScanExprContext(node->ps_ExprContext);
00120 
00121     /* And do node-type-specific processing */
00122     switch (nodeTag(node))
00123     {
00124         case T_ResultState:
00125             ExecReScanResult((ResultState *) node);
00126             break;
00127 
00128         case T_ModifyTableState:
00129             ExecReScanModifyTable((ModifyTableState *) node);
00130             break;
00131 
00132         case T_AppendState:
00133             ExecReScanAppend((AppendState *) node);
00134             break;
00135 
00136         case T_MergeAppendState:
00137             ExecReScanMergeAppend((MergeAppendState *) node);
00138             break;
00139 
00140         case T_RecursiveUnionState:
00141             ExecReScanRecursiveUnion((RecursiveUnionState *) node);
00142             break;
00143 
00144         case T_BitmapAndState:
00145             ExecReScanBitmapAnd((BitmapAndState *) node);
00146             break;
00147 
00148         case T_BitmapOrState:
00149             ExecReScanBitmapOr((BitmapOrState *) node);
00150             break;
00151 
00152         case T_SeqScanState:
00153             ExecReScanSeqScan((SeqScanState *) node);
00154             break;
00155 
00156         case T_IndexScanState:
00157             ExecReScanIndexScan((IndexScanState *) node);
00158             break;
00159 
00160         case T_IndexOnlyScanState:
00161             ExecReScanIndexOnlyScan((IndexOnlyScanState *) node);
00162             break;
00163 
00164         case T_BitmapIndexScanState:
00165             ExecReScanBitmapIndexScan((BitmapIndexScanState *) node);
00166             break;
00167 
00168         case T_BitmapHeapScanState:
00169             ExecReScanBitmapHeapScan((BitmapHeapScanState *) node);
00170             break;
00171 
00172         case T_TidScanState:
00173             ExecReScanTidScan((TidScanState *) node);
00174             break;
00175 
00176         case T_SubqueryScanState:
00177             ExecReScanSubqueryScan((SubqueryScanState *) node);
00178             break;
00179 
00180         case T_FunctionScanState:
00181             ExecReScanFunctionScan((FunctionScanState *) node);
00182             break;
00183 
00184         case T_ValuesScanState:
00185             ExecReScanValuesScan((ValuesScanState *) node);
00186             break;
00187 
00188         case T_CteScanState:
00189             ExecReScanCteScan((CteScanState *) node);
00190             break;
00191 
00192         case T_WorkTableScanState:
00193             ExecReScanWorkTableScan((WorkTableScanState *) node);
00194             break;
00195 
00196         case T_ForeignScanState:
00197             ExecReScanForeignScan((ForeignScanState *) node);
00198             break;
00199 
00200         case T_NestLoopState:
00201             ExecReScanNestLoop((NestLoopState *) node);
00202             break;
00203 
00204         case T_MergeJoinState:
00205             ExecReScanMergeJoin((MergeJoinState *) node);
00206             break;
00207 
00208         case T_HashJoinState:
00209             ExecReScanHashJoin((HashJoinState *) node);
00210             break;
00211 
00212         case T_MaterialState:
00213             ExecReScanMaterial((MaterialState *) node);
00214             break;
00215 
00216         case T_SortState:
00217             ExecReScanSort((SortState *) node);
00218             break;
00219 
00220         case T_GroupState:
00221             ExecReScanGroup((GroupState *) node);
00222             break;
00223 
00224         case T_AggState:
00225             ExecReScanAgg((AggState *) node);
00226             break;
00227 
00228         case T_WindowAggState:
00229             ExecReScanWindowAgg((WindowAggState *) node);
00230             break;
00231 
00232         case T_UniqueState:
00233             ExecReScanUnique((UniqueState *) node);
00234             break;
00235 
00236         case T_HashState:
00237             ExecReScanHash((HashState *) node);
00238             break;
00239 
00240         case T_SetOpState:
00241             ExecReScanSetOp((SetOpState *) node);
00242             break;
00243 
00244         case T_LockRowsState:
00245             ExecReScanLockRows((LockRowsState *) node);
00246             break;
00247 
00248         case T_LimitState:
00249             ExecReScanLimit((LimitState *) node);
00250             break;
00251 
00252         default:
00253             elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node));
00254             break;
00255     }
00256 
00257     if (node->chgParam != NULL)
00258     {
00259         bms_free(node->chgParam);
00260         node->chgParam = NULL;
00261     }
00262 }
00263 
00264 /*
00265  * ExecMarkPos
00266  *
00267  * Marks the current scan position.
00268  */
00269 void
00270 ExecMarkPos(PlanState *node)
00271 {
00272     switch (nodeTag(node))
00273     {
00274         case T_SeqScanState:
00275             ExecSeqMarkPos((SeqScanState *) node);
00276             break;
00277 
00278         case T_IndexScanState:
00279             ExecIndexMarkPos((IndexScanState *) node);
00280             break;
00281 
00282         case T_IndexOnlyScanState:
00283             ExecIndexOnlyMarkPos((IndexOnlyScanState *) node);
00284             break;
00285 
00286         case T_TidScanState:
00287             ExecTidMarkPos((TidScanState *) node);
00288             break;
00289 
00290         case T_ValuesScanState:
00291             ExecValuesMarkPos((ValuesScanState *) node);
00292             break;
00293 
00294         case T_MaterialState:
00295             ExecMaterialMarkPos((MaterialState *) node);
00296             break;
00297 
00298         case T_SortState:
00299             ExecSortMarkPos((SortState *) node);
00300             break;
00301 
00302         case T_ResultState:
00303             ExecResultMarkPos((ResultState *) node);
00304             break;
00305 
00306         default:
00307             /* don't make hard error unless caller asks to restore... */
00308             elog(DEBUG2, "unrecognized node type: %d", (int) nodeTag(node));
00309             break;
00310     }
00311 }
00312 
00313 /*
00314  * ExecRestrPos
00315  *
00316  * restores the scan position previously saved with ExecMarkPos()
00317  *
00318  * NOTE: the semantics of this are that the first ExecProcNode following
00319  * the restore operation will yield the same tuple as the first one following
00320  * the mark operation.  It is unspecified what happens to the plan node's
00321  * result TupleTableSlot.  (In most cases the result slot is unchanged by
00322  * a restore, but the node may choose to clear it or to load it with the
00323  * restored-to tuple.)  Hence the caller should discard any previously
00324  * returned TupleTableSlot after doing a restore.
00325  */
00326 void
00327 ExecRestrPos(PlanState *node)
00328 {
00329     switch (nodeTag(node))
00330     {
00331         case T_SeqScanState:
00332             ExecSeqRestrPos((SeqScanState *) node);
00333             break;
00334 
00335         case T_IndexScanState:
00336             ExecIndexRestrPos((IndexScanState *) node);
00337             break;
00338 
00339         case T_IndexOnlyScanState:
00340             ExecIndexOnlyRestrPos((IndexOnlyScanState *) node);
00341             break;
00342 
00343         case T_TidScanState:
00344             ExecTidRestrPos((TidScanState *) node);
00345             break;
00346 
00347         case T_ValuesScanState:
00348             ExecValuesRestrPos((ValuesScanState *) node);
00349             break;
00350 
00351         case T_MaterialState:
00352             ExecMaterialRestrPos((MaterialState *) node);
00353             break;
00354 
00355         case T_SortState:
00356             ExecSortRestrPos((SortState *) node);
00357             break;
00358 
00359         case T_ResultState:
00360             ExecResultRestrPos((ResultState *) node);
00361             break;
00362 
00363         default:
00364             elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node));
00365             break;
00366     }
00367 }
00368 
00369 /*
00370  * ExecSupportsMarkRestore - does a plan type support mark/restore?
00371  *
00372  * XXX Ideally, all plan node types would support mark/restore, and this
00373  * wouldn't be needed.  For now, this had better match the routines above.
00374  * But note the test is on Plan nodetype, not PlanState nodetype.
00375  *
00376  * (However, since the only present use of mark/restore is in mergejoin,
00377  * there is no need to support mark/restore in any plan type that is not
00378  * capable of generating ordered output.  So the seqscan, tidscan,
00379  * and valuesscan support is actually useless code at present.)
00380  */
00381 bool
00382 ExecSupportsMarkRestore(NodeTag plantype)
00383 {
00384     switch (plantype)
00385     {
00386         case T_SeqScan:
00387         case T_IndexScan:
00388         case T_IndexOnlyScan:
00389         case T_TidScan:
00390         case T_ValuesScan:
00391         case T_Material:
00392         case T_Sort:
00393             return true;
00394 
00395         case T_Result:
00396 
00397             /*
00398              * T_Result only supports mark/restore if it has a child plan that
00399              * does, so we do not have enough information to give a really
00400              * correct answer.  However, for current uses it's enough to
00401              * always say "false", because this routine is not asked about
00402              * gating Result plans, only base-case Results.
00403              */
00404             return false;
00405 
00406         default:
00407             break;
00408     }
00409 
00410     return false;
00411 }
00412 
00413 /*
00414  * ExecSupportsBackwardScan - does a plan type support backwards scanning?
00415  *
00416  * Ideally, all plan types would support backwards scan, but that seems
00417  * unlikely to happen soon.  In some cases, a plan node passes the backwards
00418  * scan down to its children, and so supports backwards scan only if its
00419  * children do.  Therefore, this routine must be passed a complete plan tree.
00420  */
00421 bool
00422 ExecSupportsBackwardScan(Plan *node)
00423 {
00424     if (node == NULL)
00425         return false;
00426 
00427     switch (nodeTag(node))
00428     {
00429         case T_Result:
00430             if (outerPlan(node) != NULL)
00431                 return ExecSupportsBackwardScan(outerPlan(node)) &&
00432                     TargetListSupportsBackwardScan(node->targetlist);
00433             else
00434                 return false;
00435 
00436         case T_Append:
00437             {
00438                 ListCell   *l;
00439 
00440                 foreach(l, ((Append *) node)->appendplans)
00441                 {
00442                     if (!ExecSupportsBackwardScan((Plan *) lfirst(l)))
00443                         return false;
00444                 }
00445                 /* need not check tlist because Append doesn't evaluate it */
00446                 return true;
00447             }
00448 
00449         case T_SeqScan:
00450         case T_TidScan:
00451         case T_FunctionScan:
00452         case T_ValuesScan:
00453         case T_CteScan:
00454             return TargetListSupportsBackwardScan(node->targetlist);
00455 
00456         case T_IndexScan:
00457             return IndexSupportsBackwardScan(((IndexScan *) node)->indexid) &&
00458                 TargetListSupportsBackwardScan(node->targetlist);
00459 
00460         case T_IndexOnlyScan:
00461             return IndexSupportsBackwardScan(((IndexOnlyScan *) node)->indexid) &&
00462                 TargetListSupportsBackwardScan(node->targetlist);
00463 
00464         case T_SubqueryScan:
00465             return ExecSupportsBackwardScan(((SubqueryScan *) node)->subplan) &&
00466                 TargetListSupportsBackwardScan(node->targetlist);
00467 
00468         case T_Material:
00469         case T_Sort:
00470             /* these don't evaluate tlist */
00471             return true;
00472 
00473         case T_LockRows:
00474         case T_Limit:
00475             /* these don't evaluate tlist */
00476             return ExecSupportsBackwardScan(outerPlan(node));
00477 
00478         default:
00479             return false;
00480     }
00481 }
00482 
00483 /*
00484  * If the tlist contains set-returning functions, we can't support backward
00485  * scan, because the TupFromTlist code is direction-ignorant.
00486  */
00487 static bool
00488 TargetListSupportsBackwardScan(List *targetlist)
00489 {
00490     if (expression_returns_set((Node *) targetlist))
00491         return false;
00492     return true;
00493 }
00494 
00495 /*
00496  * An IndexScan or IndexOnlyScan node supports backward scan only if the
00497  * index's AM does.
00498  */
00499 static bool
00500 IndexSupportsBackwardScan(Oid indexid)
00501 {
00502     bool        result;
00503     HeapTuple   ht_idxrel;
00504     HeapTuple   ht_am;
00505     Form_pg_class idxrelrec;
00506     Form_pg_am  amrec;
00507 
00508     /* Fetch the pg_class tuple of the index relation */
00509     ht_idxrel = SearchSysCache1(RELOID, ObjectIdGetDatum(indexid));
00510     if (!HeapTupleIsValid(ht_idxrel))
00511         elog(ERROR, "cache lookup failed for relation %u", indexid);
00512     idxrelrec = (Form_pg_class) GETSTRUCT(ht_idxrel);
00513 
00514     /* Fetch the pg_am tuple of the index' access method */
00515     ht_am = SearchSysCache1(AMOID, ObjectIdGetDatum(idxrelrec->relam));
00516     if (!HeapTupleIsValid(ht_am))
00517         elog(ERROR, "cache lookup failed for access method %u",
00518              idxrelrec->relam);
00519     amrec = (Form_pg_am) GETSTRUCT(ht_am);
00520 
00521     result = amrec->amcanbackward;
00522 
00523     ReleaseSysCache(ht_idxrel);
00524     ReleaseSysCache(ht_am);
00525 
00526     return result;
00527 }
00528 
00529 /*
00530  * ExecMaterializesOutput - does a plan type materialize its output?
00531  *
00532  * Returns true if the plan node type is one that automatically materializes
00533  * its output (typically by keeping it in a tuplestore).  For such plans,
00534  * a rescan without any parameter change will have zero startup cost and
00535  * very low per-tuple cost.
00536  */
00537 bool
00538 ExecMaterializesOutput(NodeTag plantype)
00539 {
00540     switch (plantype)
00541     {
00542         case T_Material:
00543         case T_FunctionScan:
00544         case T_CteScan:
00545         case T_WorkTableScan:
00546         case T_Sort:
00547             return true;
00548 
00549         default:
00550             break;
00551     }
00552 
00553     return false;
00554 }