createplan.c

来自「postgresql8.3.4源码,开源数据库」· C语言 代码 · 共 2,120 行 · 第 1/5 页

C
2,120
字号
/*------------------------------------------------------------------------- * * createplan.c *	  Routines to create the desired plan for processing a query. *	  Planning is complete, we just need to convert the selected *	  Path into a Plan. * * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION *	  $PostgreSQL: pgsql/src/backend/optimizer/plan/createplan.c,v 1.237.2.1 2008/04/17 21:22:23 tgl Exp $ * *------------------------------------------------------------------------- */#include "postgres.h"#include <limits.h>#include "access/skey.h"#include "nodes/makefuncs.h"#include "optimizer/clauses.h"#include "optimizer/cost.h"#include "optimizer/plancat.h"#include "optimizer/planmain.h"#include "optimizer/predtest.h"#include "optimizer/restrictinfo.h"#include "optimizer/tlist.h"#include "optimizer/var.h"#include "parser/parse_clause.h"#include "parser/parse_expr.h"#include "parser/parsetree.h"#include "utils/lsyscache.h"static Plan *create_scan_plan(PlannerInfo *root, Path *best_path);static List *build_relation_tlist(RelOptInfo *rel);static bool use_physical_tlist(RelOptInfo *rel);static void disuse_physical_tlist(Plan *plan, Path *path);static Plan *create_gating_plan(PlannerInfo *root, Plan *plan, List *quals);static Plan *create_join_plan(PlannerInfo *root, JoinPath *best_path);static Plan *create_append_plan(PlannerInfo *root, AppendPath *best_path);static Result *create_result_plan(PlannerInfo *root, ResultPath *best_path);static Material *create_material_plan(PlannerInfo *root, MaterialPath *best_path);static Plan *create_unique_plan(PlannerInfo *root, UniquePath *best_path);static SeqScan *create_seqscan_plan(PlannerInfo *root, Path *best_path,					List *tlist, List *scan_clauses);static IndexScan *create_indexscan_plan(PlannerInfo *root, IndexPath *best_path,					  List *tlist, List *scan_clauses,					  List **nonlossy_clauses);static BitmapHeapScan *create_bitmap_scan_plan(PlannerInfo *root,						BitmapHeapPath *best_path,						List *tlist, List *scan_clauses);static Plan *create_bitmap_subplan(PlannerInfo *root, Path *bitmapqual,					  List **qual, List **indexqual);static TidScan *create_tidscan_plan(PlannerInfo *root, TidPath *best_path,					List *tlist, List *scan_clauses);static SubqueryScan *create_subqueryscan_plan(PlannerInfo *root, Path *best_path,						 List *tlist, List *scan_clauses);static FunctionScan *create_functionscan_plan(PlannerInfo *root, Path *best_path,						 List *tlist, List *scan_clauses);static ValuesScan *create_valuesscan_plan(PlannerInfo *root, Path *best_path,					   List *tlist, List *scan_clauses);static NestLoop *create_nestloop_plan(PlannerInfo *root, NestPath *best_path,					 Plan *outer_plan, Plan *inner_plan);static MergeJoin *create_mergejoin_plan(PlannerInfo *root, MergePath *best_path,					  Plan *outer_plan, Plan *inner_plan);static HashJoin *create_hashjoin_plan(PlannerInfo *root, HashPath *best_path,					 Plan *outer_plan, Plan *inner_plan);static void fix_indexqual_references(List *indexquals, IndexPath *index_path,						 List **fixed_indexquals,						 List **nonlossy_indexquals,						 List **indexstrategy,						 List **indexsubtype);static Node *fix_indexqual_operand(Node *node, IndexOptInfo *index,					  Oid *opfamily);static List *get_switched_clauses(List *clauses, Relids outerrelids);static List *order_qual_clauses(PlannerInfo *root, List *clauses);static void copy_path_costsize(Plan *dest, Path *src);static void copy_plan_costsize(Plan *dest, Plan *src);static SeqScan *make_seqscan(List *qptlist, List *qpqual, Index scanrelid);static IndexScan *make_indexscan(List *qptlist, List *qpqual, Index scanrelid,			   Oid indexid, List *indexqual, List *indexqualorig,			   List *indexstrategy, List *indexsubtype,			   ScanDirection indexscandir);static BitmapIndexScan *make_bitmap_indexscan(Index scanrelid, Oid indexid,					  List *indexqual,					  List *indexqualorig,					  List *indexstrategy,					  List *indexsubtype);static BitmapHeapScan *make_bitmap_heapscan(List *qptlist,					 List *qpqual,					 Plan *lefttree,					 List *bitmapqualorig,					 Index scanrelid);static TidScan *make_tidscan(List *qptlist, List *qpqual, Index scanrelid,			 List *tidquals);static FunctionScan *make_functionscan(List *qptlist, List *qpqual,				  Index scanrelid, Node *funcexpr, List *funccolnames,				  List *funccoltypes, List *funccoltypmods);static ValuesScan *make_valuesscan(List *qptlist, List *qpqual,				Index scanrelid, List *values_lists);static BitmapAnd *make_bitmap_and(List *bitmapplans);static BitmapOr *make_bitmap_or(List *bitmapplans);static NestLoop *make_nestloop(List *tlist,			  List *joinclauses, List *otherclauses,			  Plan *lefttree, Plan *righttree,			  JoinType jointype);static HashJoin *make_hashjoin(List *tlist,			  List *joinclauses, List *otherclauses,			  List *hashclauses,			  Plan *lefttree, Plan *righttree,			  JoinType jointype);static Hash *make_hash(Plan *lefttree);static MergeJoin *make_mergejoin(List *tlist,			   List *joinclauses, List *otherclauses,			   List *mergeclauses,			   Oid *mergefamilies,			   int *mergestrategies,			   bool *mergenullsfirst,			   Plan *lefttree, Plan *righttree,			   JoinType jointype);static Sort *make_sort(PlannerInfo *root, Plan *lefttree, int numCols,		  AttrNumber *sortColIdx, Oid *sortOperators, bool *nullsFirst,		  double limit_tuples);static Material *make_material(Plan *lefttree);/* * create_plan *	  Creates the access plan for a query by tracing backwards through the *	  desired chain of pathnodes, starting at the node 'best_path'.  For *	  every pathnode found, we create a corresponding plan node containing *	  appropriate id, target list, and qualification information. * *	  The tlists and quals in the plan tree are still in planner format, *	  ie, Vars still correspond to the parser's numbering.  This will be *	  fixed later by setrefs.c. * *	  best_path is the best access path * *	  Returns a Plan tree. */Plan *create_plan(PlannerInfo *root, Path *best_path){	Plan	   *plan;	switch (best_path->pathtype)	{		case T_SeqScan:		case T_IndexScan:		case T_BitmapHeapScan:		case T_TidScan:		case T_SubqueryScan:		case T_FunctionScan:		case T_ValuesScan:			plan = create_scan_plan(root, best_path);			break;		case T_HashJoin:		case T_MergeJoin:		case T_NestLoop:			plan = create_join_plan(root,									(JoinPath *) best_path);			break;		case T_Append:			plan = create_append_plan(root,									  (AppendPath *) best_path);			break;		case T_Result:			plan = (Plan *) create_result_plan(root,											   (ResultPath *) best_path);			break;		case T_Material:			plan = (Plan *) create_material_plan(root,												 (MaterialPath *) best_path);			break;		case T_Unique:			plan = create_unique_plan(root,									  (UniquePath *) best_path);			break;		default:			elog(ERROR, "unrecognized node type: %d",				 (int) best_path->pathtype);			plan = NULL;		/* keep compiler quiet */			break;	}	return plan;}/* * create_scan_plan *	 Create a scan plan for the parent relation of 'best_path'. */static Plan *create_scan_plan(PlannerInfo *root, Path *best_path){	RelOptInfo *rel = best_path->parent;	List	   *tlist;	List	   *scan_clauses;	Plan	   *plan;	/*	 * For table scans, rather than using the relation targetlist (which is	 * only those Vars actually needed by the query), we prefer to generate a	 * tlist containing all Vars in order.	This will allow the executor to	 * optimize away projection of the table tuples, if possible.  (Note that	 * planner.c may replace the tlist we generate here, forcing projection to	 * occur.)	 */	if (use_physical_tlist(rel))	{		tlist = build_physical_tlist(root, rel);		/* if fail because of dropped cols, use regular method */		if (tlist == NIL)			tlist = build_relation_tlist(rel);	}	else		tlist = build_relation_tlist(rel);	/*	 * Extract the relevant restriction clauses from the parent relation. The	 * executor must apply all these restrictions during the scan, except for	 * pseudoconstants which we'll take care of below.	 */	scan_clauses = rel->baserestrictinfo;	switch (best_path->pathtype)	{		case T_SeqScan:			plan = (Plan *) create_seqscan_plan(root,												best_path,												tlist,												scan_clauses);			break;		case T_IndexScan:			plan = (Plan *) create_indexscan_plan(root,												  (IndexPath *) best_path,												  tlist,												  scan_clauses,												  NULL);			break;		case T_BitmapHeapScan:			plan = (Plan *) create_bitmap_scan_plan(root,												(BitmapHeapPath *) best_path,													tlist,													scan_clauses);			break;		case T_TidScan:			plan = (Plan *) create_tidscan_plan(root,												(TidPath *) best_path,												tlist,												scan_clauses);			break;		case T_SubqueryScan:			plan = (Plan *) create_subqueryscan_plan(root,													 best_path,													 tlist,													 scan_clauses);			break;		case T_FunctionScan:			plan = (Plan *) create_functionscan_plan(root,													 best_path,													 tlist,													 scan_clauses);			break;		case T_ValuesScan:			plan = (Plan *) create_valuesscan_plan(root,												   best_path,												   tlist,												   scan_clauses);			break;		default:			elog(ERROR, "unrecognized node type: %d",				 (int) best_path->pathtype);			plan = NULL;		/* keep compiler quiet */			break;	}	/*	 * If there are any pseudoconstant clauses attached to this node, insert a	 * gating Result node that evaluates the pseudoconstants as one-time	 * quals.	 */	if (root->hasPseudoConstantQuals)		plan = create_gating_plan(root, plan, scan_clauses);	return plan;}/* * Build a target list (ie, a list of TargetEntry) for a relation. */static List *build_relation_tlist(RelOptInfo *rel){	List	   *tlist = NIL;	int			resno = 1;	ListCell   *v;	foreach(v, rel->reltargetlist)	{		/* Do we really need to copy here?	Not sure */		Var		   *var = (Var *) copyObject(lfirst(v));		tlist = lappend(tlist, makeTargetEntry((Expr *) var,											   resno,											   NULL,											   false));		resno++;	}	return tlist;}/* * use_physical_tlist *		Decide whether to use a tlist matching relation structure, *		rather than only those Vars actually referenced. */static booluse_physical_tlist(RelOptInfo *rel){	int			i;	/*	 * We can do this for real relation scans, subquery scans, function scans,	 * and values scans (but not for, eg, joins).	 */	if (rel->rtekind != RTE_RELATION &&		rel->rtekind != RTE_SUBQUERY &&		rel->rtekind != RTE_FUNCTION &&		rel->rtekind != RTE_VALUES)		return false;	/*	 * Can't do it with inheritance cases either (mainly because Append	 * doesn't project).	 */	if (rel->reloptkind != RELOPT_BASEREL)		return false;	/*	 * Can't do it if any system columns or whole-row Vars are requested,	 * either.	(This could possibly be fixed but would take some fragile	 * assumptions in setrefs.c, I think.)	 */	for (i = rel->min_attr; i <= 0; i++)	{		if (!bms_is_empty(rel->attr_needed[i - rel->min_attr]))			return false;	}	return true;}/* * disuse_physical_tlist *		Switch a plan node back to emitting only Vars actually referenced. * * If the plan node immediately above a scan would prefer to get only * needed Vars and not a physical tlist, it must call this routine to * undo the decision made by use_physical_tlist().	Currently, Hash, Sort, * and Material nodes want this, so they don't have to store useless columns. */static voiddisuse_physical_tlist(Plan *plan, Path *path){	/* Only need to undo it for path types handled by create_scan_plan() */	switch (path->pathtype)	{		case T_SeqScan:		case T_IndexScan:		case T_BitmapHeapScan:		case T_TidScan:		case T_SubqueryScan:		case T_FunctionScan:		case T_ValuesScan:			plan->targetlist = build_relation_tlist(path->parent);			break;		default:			break;	}}/* * create_gating_plan *	  Deal with pseudoconstant qual clauses * * If the node's quals list includes any pseudoconstant quals, put them * into a gating Result node atop the already-built plan.  Otherwise, * return the plan as-is. * * Note that we don't change cost or size estimates when doing gating. * The costs of qual eval were already folded into the plan's startup cost. * Leaving the size alone amounts to assuming that the gating qual will * succeed, which is the conservative estimate for planning upper queries. * We certainly don't want to assume the output size is zero (unless the * gating qual is actually constant FALSE, and that case is dealt with in * clausesel.c).  Interpolating between the two cases is silly, because * it doesn't reflect what will really happen at runtime, and besides which * in most cases we have only a very bad idea of the probability of the gating * qual being true. */static Plan *create_gating_plan(PlannerInfo *root, Plan *plan, List *quals){	List	   *pseudoconstants;	/* Sort into desirable execution order while still in RestrictInfo form */	quals = order_qual_clauses(root, quals);	/* Pull out any pseudoconstant quals from the RestrictInfo list */	pseudoconstants = extract_actual_clauses(quals, true);	if (!pseudoconstants)

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?