⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 createplan.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 5 页
字号:
/*------------------------------------------------------------------------- * * 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-2005, 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.202.2.4 2006/05/18 18:57:37 tgl Exp $ * *------------------------------------------------------------------------- */#include "postgres.h"#include <limits.h>#include "nodes/makefuncs.h"#include "nodes/nodeFuncs.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/parsetree.h"#include "parser/parse_clause.h"#include "parser/parse_expr.h"#include "utils/lsyscache.h"#include "utils/syscache.h"static Scan *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 Join *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 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 *opclass);static List *get_switched_clauses(List *clauses, Relids outerrelids);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 *tideval);static FunctionScan *make_functionscan(List *qptlist, List *qpqual,				  Index scanrelid);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,			   Plan *lefttree, Plan *righttree,			   JoinType jointype);static Sort *make_sort(PlannerInfo *root, Plan *lefttree, int numCols,		  AttrNumber *sortColIdx, Oid *sortOperators);static Sort *make_sort_from_pathkeys(PlannerInfo *root, Plan *lefttree,						List *pathkeys);/* * 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: *	  (1) Create a corresponding plan node containing appropriate id, *		  target list, and qualification information. *	  (2) Modify qual clauses of join nodes so that subplan attributes are *		  referenced using relative values. *	  (3) Target lists are not modified, but will be in 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:			plan = (Plan *) create_scan_plan(root, best_path);			break;		case T_HashJoin:		case T_MergeJoin:		case T_NestLoop:			plan = (Plan *) create_join_plan(root,											 (JoinPath *) best_path);			break;		case T_Append:			plan = (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 = (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'. * *	 Returns a Plan node. */static Scan *create_scan_plan(PlannerInfo *root, Path *best_path){	RelOptInfo *rel = best_path->parent;	List	   *tlist;	List	   *scan_clauses;	Scan	   *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.	 */	scan_clauses = rel->baserestrictinfo;	switch (best_path->pathtype)	{		case T_SeqScan:			plan = (Scan *) create_seqscan_plan(root,												best_path,												tlist,												scan_clauses);			break;		case T_IndexScan:			plan = (Scan *) create_indexscan_plan(root,												  (IndexPath *) best_path,												  tlist,												  scan_clauses,												  NULL);			break;		case T_BitmapHeapScan:			plan = (Scan *) create_bitmap_scan_plan(root,												(BitmapHeapPath *) best_path,													tlist,													scan_clauses);			break;		case T_TidScan:			plan = (Scan *) create_tidscan_plan(root,												(TidPath *) best_path,												tlist,												scan_clauses);			break;		case T_SubqueryScan:			plan = (Scan *) create_subqueryscan_plan(root,													 best_path,													 tlist,													 scan_clauses);			break;		case T_FunctionScan:			plan = (Scan *) create_functionscan_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;	}	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, and function	 * scans (but not for, eg, joins).	 */	if (rel->rtekind != RTE_RELATION &&		rel->rtekind != RTE_SUBQUERY &&		rel->rtekind != RTE_FUNCTION)		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:			plan->targetlist = build_relation_tlist(path->parent);			break;		default:			break;	}}/* * create_join_plan *	  Create a join plan for 'best_path' and (recursively) plans for its *	  inner and outer paths. * *	  Returns a Plan node. */static Join *create_join_plan(PlannerInfo *root, JoinPath *best_path){	Plan	   *outer_plan;	Plan	   *inner_plan;	Join	   *plan;	outer_plan = create_plan(root, best_path->outerjoinpath);	inner_plan = create_plan(root, best_path->innerjoinpath);	switch (best_path->path.pathtype)	{		case T_MergeJoin:			plan = (Join *) create_mergejoin_plan(root,												  (MergePath *) best_path,												  outer_plan,												  inner_plan);			break;		case T_HashJoin:			plan = (Join *) create_hashjoin_plan(root,												 (HashPath *) best_path,												 outer_plan,												 inner_plan);			break;		case T_NestLoop:			plan = (Join *) create_nestloop_plan(root,												 (NestPath *) best_path,												 outer_plan,												 inner_plan);			break;		default:			elog(ERROR, "unrecognized node type: %d",				 (int) best_path->path.pathtype);			plan = NULL;		/* keep compiler quiet */			break;	}#ifdef NOT_USED	/*	 * * Expensive function pullups may have pulled local predicates * into	 * this path node.	Put them in the qpqual of the plan node. * JMH,	 * 6/15/92	 */	if (get_loc_restrictinfo(best_path) != NIL)		set_qpqual((Plan) plan,				   list_concat(get_qpqual((Plan) plan),					   get_actual_clauses(get_loc_restrictinfo(best_path))));#endif	return plan;}/* * create_append_plan *	  Create an Append plan for 'best_path' and (recursively) plans *	  for its subpaths. * *	  Returns a Plan node. */static Plan *create_append_plan(PlannerInfo *root, AppendPath *best_path){	Append	   *plan;	List	   *tlist = build_relation_tlist(best_path->path.parent);	List	   *subplans = NIL;	ListCell   *subpaths;	/*	 * It is possible for the subplans list to contain only one entry, or even	 * no entries.	Handle these cases specially.	 *	 * XXX ideally, if there's just one entry, we'd not bother to generate an	 * Append node but just return the single child.  At the moment this does	 * not work because the varno of the child scan plan won't match the

⌨️ 快捷键说明

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