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

📄 createplan.c

📁 PostgreSQL7.4.6 for 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-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION *	  $Header: /cvsroot/pgsql/src/backend/optimizer/plan/createplan.c,v 1.157.2.3 2004/02/29 17:36:48 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/paths.h"#include "optimizer/plancat.h"#include "optimizer/planmain.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(Query *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(Query *root, JoinPath *best_path);static Append *create_append_plan(Query *root, AppendPath *best_path);static Result *create_result_plan(Query *root, ResultPath *best_path);static Material *create_material_plan(Query *root, MaterialPath *best_path);static Plan *create_unique_plan(Query *root, UniquePath *best_path);static SeqScan *create_seqscan_plan(Path *best_path, List *tlist,					List *scan_clauses);static IndexScan *create_indexscan_plan(Query *root, IndexPath *best_path,					  List *tlist, List *scan_clauses);static TidScan *create_tidscan_plan(TidPath *best_path, List *tlist,					List *scan_clauses);static SubqueryScan *create_subqueryscan_plan(Path *best_path,						 List *tlist, List *scan_clauses);static FunctionScan *create_functionscan_plan(Path *best_path,						 List *tlist, List *scan_clauses);static NestLoop *create_nestloop_plan(Query *root, NestPath *best_path,					 Plan *outer_plan, Plan *inner_plan);static MergeJoin *create_mergejoin_plan(Query *root, MergePath *best_path,					  Plan *outer_plan, Plan *inner_plan);static HashJoin *create_hashjoin_plan(Query *root, HashPath *best_path,					 Plan *outer_plan, Plan *inner_plan);static void fix_indxqual_references(List *indexquals, IndexPath *index_path,						List **fixed_indexquals,						List **recheck_indexquals);static void fix_indxqual_sublist(List *indexqual,					 Relids baserelids, int baserelid,					 IndexOptInfo *index,					 List **fixed_quals, List **recheck_quals);static Node *fix_indxqual_operand(Node *node, int baserelid,					 IndexOptInfo *index,					 Oid *opclass);static List *get_switched_clauses(List *clauses, Relids outerrelids);static List *order_qual_clauses(Query *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,			   List *indxid, List *indxqual,			   List *indxqualorig,			   ScanDirection indexscandir);static TidScan *make_tidscan(List *qptlist, List *qpqual, Index scanrelid,			 List *tideval);static FunctionScan *make_functionscan(List *qptlist, List *qpqual,				  Index scanrelid);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(List *tlist, List *hashkeys, Plan *lefttree);static MergeJoin *make_mergejoin(List *tlist,			   List *joinclauses, List *otherclauses,			   List *mergeclauses,			   Plan *lefttree, Plan *righttree,			   JoinType jointype);static Sort *make_sort(Query *root, List *tlist, Plan *lefttree, int numCols,		  AttrNumber *sortColIdx, Oid *sortOperators);static Sort *make_sort_from_pathkeys(Query *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(Query *root, Path *best_path){	Plan	   *plan;	switch (best_path->pathtype)	{		case T_IndexScan:		case T_SeqScan:		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;	}#ifdef NOT_USED					/* fix xfunc */	/* sort clauses by cost/(1-selectivity) -- JMH 2/26/92 */	if (XfuncMode != XFUNC_OFF)	{		set_qpqual((Plan) plan,				   lisp_qsort(get_qpqual((Plan) plan),							  xfunc_clause_compare));		if (XfuncMode != XFUNC_NOR)			/* sort the disjuncts within each clause by cost -- JMH 3/4/92 */			xfunc_disjunct_sort(plan->qpqual);	}#endif	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(Query *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 = get_actual_clauses(rel->baserestrictinfo);	/* Sort clauses into best execution order */	scan_clauses = order_qual_clauses(root, scan_clauses);	switch (best_path->pathtype)	{		case T_SeqScan:			plan = (Scan *) create_seqscan_plan(best_path,												tlist,												scan_clauses);			break;		case T_IndexScan:			plan = (Scan *) create_indexscan_plan(root,												  (IndexPath *) best_path,												  tlist,												  scan_clauses);			break;		case T_TidScan:			plan = (Scan *) create_tidscan_plan((TidPath *) best_path,												tlist,												scan_clauses);			break;		case T_SubqueryScan:			plan = (Scan *) create_subqueryscan_plan(best_path,													 tlist,													 scan_clauses);			break;		case T_FunctionScan:			plan = (Scan *) create_functionscan_plan(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){	FastList	tlist;	int			resdomno = 1;	List	   *v;	FastListInit(&tlist);	foreach(v, FastListValue(&rel->reltargetlist))	{		/* Do we really need to copy here?	Not sure */		Var		   *var = (Var *) copyObject(lfirst(v));		FastAppend(&tlist, create_tl_element(var, resdomno));		resdomno++;	}	return FastListValue(&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;	/*	 * Currently, can't do this for subquery or function scans.  (This is	 * mainly because we don't have an equivalent of build_physical_tlist	 * for them; worth adding?)	 */	if (rel->rtekind != RTE_RELATION)		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 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_IndexScan:		case T_SeqScan:		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(Query *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,				   nconc(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 Append *create_append_plan(Query *root, AppendPath *best_path){	Append	   *plan;	List	   *tlist = build_relation_tlist(best_path->path.parent);	List	   *subplans = NIL;	List	   *subpaths;	foreach(subpaths, best_path->subpaths)	{		Path	   *subpath = (Path *) lfirst(subpaths);		subplans = lappend(subplans, create_plan(root, subpath));	}	plan = make_append(subplans, false, tlist);	return plan;}/* * create_result_plan *	  Create a Result plan for 'best_path' and (recursively) plans *	  for its subpaths. * *	  Returns a Plan node. */static Result *create_result_plan(Query *root, ResultPath *best_path){	Result	   *plan;	List	   *tlist;	List	   *constclauses;	Plan	   *subplan;	if (best_path->path.parent)		tlist = build_relation_tlist(best_path->path.parent);	else		tlist = NIL;			/* will be filled in later */	if (best_path->subpath)		subplan = create_plan(root, best_path->subpath);	else		subplan = NULL;	constclauses = order_qual_clauses(root, best_path->constantqual);

⌨️ 快捷键说明

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