relnode.c

来自「PostgreSQL7.4.6 for Linux」· C语言 代码 · 共 563 行 · 第 1/2 页

C
563
字号
/*------------------------------------------------------------------------- * * relnode.c *	  Relation-node lookup/construction routines * * 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/util/relnode.c,v 1.52.4.1 2003/12/08 18:20:10 tgl Exp $ * *------------------------------------------------------------------------- */#include "postgres.h"#include "optimizer/cost.h"#include "optimizer/joininfo.h"#include "optimizer/pathnode.h"#include "optimizer/plancat.h"#include "optimizer/restrictinfo.h"#include "optimizer/tlist.h"#include "parser/parsetree.h"static RelOptInfo *make_base_rel(Query *root, int relid);static void build_joinrel_tlist(Query *root, RelOptInfo *joinrel);static List *build_joinrel_restrictlist(Query *root,						   RelOptInfo *joinrel,						   RelOptInfo *outer_rel,						   RelOptInfo *inner_rel,						   JoinType jointype);static void build_joinrel_joinlist(RelOptInfo *joinrel,					   RelOptInfo *outer_rel,					   RelOptInfo *inner_rel);static List *subbuild_joinrel_restrictlist(RelOptInfo *joinrel,							  List *joininfo_list);static void subbuild_joinrel_joinlist(RelOptInfo *joinrel,						  List *joininfo_list);/* * build_base_rel *	  Construct a new base relation RelOptInfo, and put it in the query's *	  base_rel_list. */voidbuild_base_rel(Query *root, int relid){	List	   *rels;	RelOptInfo *rel;	/* Rel should not exist already */	foreach(rels, root->base_rel_list)	{		rel = (RelOptInfo *) lfirst(rels);		if (relid == rel->relid)			elog(ERROR, "rel already exists");	}	/* It should not exist as an "other" rel, either */	foreach(rels, root->other_rel_list)	{		rel = (RelOptInfo *) lfirst(rels);		if (relid == rel->relid)			elog(ERROR, "rel already exists as \"other\" rel");	}	/* No existing RelOptInfo for this base rel, so make a new one */	rel = make_base_rel(root, relid);	/* and add it to the list */	root->base_rel_list = lcons(rel, root->base_rel_list);}/* * build_other_rel *	  Returns relation entry corresponding to 'relid', creating a new one *	  if necessary.  This is for 'other' relations, which are much like *	  base relations except that they live in a different list. */RelOptInfo *build_other_rel(Query *root, int relid){	List	   *rels;	RelOptInfo *rel;	/* Already made? */	foreach(rels, root->other_rel_list)	{		rel = (RelOptInfo *) lfirst(rels);		if (relid == rel->relid)			return rel;	}	/* It should not exist as a base rel */	foreach(rels, root->base_rel_list)	{		rel = (RelOptInfo *) lfirst(rels);		if (relid == rel->relid)			elog(ERROR, "rel already exists as base rel");	}	/* No existing RelOptInfo for this other rel, so make a new one */	rel = make_base_rel(root, relid);	/* presently, must be an inheritance child rel */	Assert(rel->reloptkind == RELOPT_BASEREL);	rel->reloptkind = RELOPT_OTHER_CHILD_REL;	/* and add it to the list */	root->other_rel_list = lcons(rel, root->other_rel_list);	return rel;}/* * make_base_rel *	  Construct a base-relation RelOptInfo for the specified rangetable index. * * Common code for build_base_rel and build_other_rel. */static RelOptInfo *make_base_rel(Query *root, int relid){	RelOptInfo *rel = makeNode(RelOptInfo);	RangeTblEntry *rte = rt_fetch(relid, root->rtable);	rel->reloptkind = RELOPT_BASEREL;	rel->relids = bms_make_singleton(relid);	rel->rows = 0;	rel->width = 0;	FastListInit(&rel->reltargetlist);	rel->pathlist = NIL;	rel->cheapest_startup_path = NULL;	rel->cheapest_total_path = NULL;	rel->cheapest_unique_path = NULL;	rel->pruneable = true;	rel->relid = relid;	rel->rtekind = rte->rtekind;	/* min_attr, max_attr, attr_needed, attr_widths are set below */	rel->indexlist = NIL;	rel->pages = 0;	rel->tuples = 0;	rel->subplan = NULL;	rel->baserestrictinfo = NIL;	rel->baserestrictcost.startup = 0;	rel->baserestrictcost.per_tuple = 0;	rel->outerjoinset = NULL;	rel->joininfo = NIL;	rel->index_outer_relids = NULL;	rel->index_inner_paths = NIL;	/* Check type of rtable entry */	switch (rte->rtekind)	{		case RTE_RELATION:			/* Table --- retrieve statistics from the system catalogs */			get_relation_info(rte->relid, rel);			break;		case RTE_SUBQUERY:		case RTE_FUNCTION:			/* Subquery or function --- need only set up attr range */			/* Note: 0 is included in range to support whole-row Vars */			rel->min_attr = 0;			rel->max_attr = length(rte->eref->colnames);			break;		default:			elog(ERROR, "unrecognized RTE kind: %d",				 (int) rte->rtekind);			break;	}	Assert(rel->max_attr >= rel->min_attr);	rel->attr_needed = (Relids *)		palloc0((rel->max_attr - rel->min_attr + 1) * sizeof(Relids));	rel->attr_widths = (int32 *)		palloc0((rel->max_attr - rel->min_attr + 1) * sizeof(int32));	return rel;}/* * find_base_rel *	  Find a base or other relation entry, which must already exist *	  (since we'd have no idea which list to add it to). */RelOptInfo *find_base_rel(Query *root, int relid){	List	   *rels;	RelOptInfo *rel;	foreach(rels, root->base_rel_list)	{		rel = (RelOptInfo *) lfirst(rels);		if (relid == rel->relid)			return rel;	}	foreach(rels, root->other_rel_list)	{		rel = (RelOptInfo *) lfirst(rels);		if (relid == rel->relid)			return rel;	}	elog(ERROR, "no relation entry for relid %d", relid);	return NULL;				/* keep compiler quiet */}/* * find_join_rel *	  Returns relation entry corresponding to 'relids' (a set of RT indexes), *	  or NULL if none exists.  This is for join relations. * * Note: there is probably no good reason for this to be called from * anywhere except build_join_rel, but keep it as a separate routine * just in case. */static RelOptInfo *find_join_rel(Query *root, Relids relids){	List	   *joinrels;	foreach(joinrels, root->join_rel_list)	{		RelOptInfo *rel = (RelOptInfo *) lfirst(joinrels);		if (bms_equal(rel->relids, relids))			return rel;	}	return NULL;}/* * build_join_rel *	  Returns relation entry corresponding to the union of two given rels, *	  creating a new relation entry if none already exists. * * 'joinrelids' is the Relids set that uniquely identifies the join * 'outer_rel' and 'inner_rel' are relation nodes for the relations to be *		joined * 'jointype': type of join (inner/outer) * 'restrictlist_ptr': result variable.  If not NULL, *restrictlist_ptr *		receives the list of RestrictInfo nodes that apply to this *		particular pair of joinable relations. * * restrictlist_ptr makes the routine's API a little grotty, but it saves * duplicated calculation of the restrictlist... */RelOptInfo *build_join_rel(Query *root,			   Relids joinrelids,			   RelOptInfo *outer_rel,			   RelOptInfo *inner_rel,			   JoinType jointype,			   List **restrictlist_ptr){	RelOptInfo *joinrel;	List	   *restrictlist;	/*	 * See if we already have a joinrel for this set of base rels.	 */	joinrel = find_join_rel(root, joinrelids);	if (joinrel)	{		/*		 * Yes, so we only need to figure the restrictlist for this		 * particular pair of component relations.		 */		if (restrictlist_ptr)			*restrictlist_ptr = build_joinrel_restrictlist(root,														   joinrel,														   outer_rel,														   inner_rel,														   jointype);		return joinrel;

⌨️ 快捷键说明

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