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

📄 relnode.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 2 页
字号:
/*------------------------------------------------------------------------- * * relnode.c *	  Relation-node lookup/construction routines * * 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/util/relnode.c,v 1.72.2.1 2005/11/22 18:23:12 momjian 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"#include "utils/hsearch.h"typedef struct JoinHashEntry{	Relids		join_relids;	/* hash key --- MUST BE FIRST */	RelOptInfo *join_rel;} JoinHashEntry;static RelOptInfo *make_reloptinfo(PlannerInfo *root, int relid,				RelOptKind reloptkind);static void build_joinrel_tlist(PlannerInfo *root, RelOptInfo *joinrel,					RelOptInfo *input_rel);static List *build_joinrel_restrictlist(PlannerInfo *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_array. */voidbuild_base_rel(PlannerInfo *root, int relid){	Assert(relid > 0);	/* Rel should not exist already */	if (relid < root->base_rel_array_size &&		root->base_rel_array[relid] != NULL)		elog(ERROR, "rel already exists");	/* No existing RelOptInfo for this base rel, so make a new one */	(void) make_reloptinfo(root, relid, RELOPT_BASEREL);}/* * 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 have a different RelOptKind. */RelOptInfo *build_other_rel(PlannerInfo *root, int relid){	RelOptInfo *rel;	Assert(relid > 0);	/* Already made? */	if (relid < root->base_rel_array_size)	{		rel = root->base_rel_array[relid];		if (rel)		{			/* it should not exist as a base rel */			if (rel->reloptkind == RELOPT_BASEREL)				elog(ERROR, "rel already exists as base rel");			/* otherwise, A-OK */			return rel;		}	}	/* No existing RelOptInfo for this other rel, so make a new one */	/* presently, must be an inheritance child rel */	rel = make_reloptinfo(root, relid, RELOPT_OTHER_CHILD_REL);	return rel;}/* * make_reloptinfo *	  Construct a RelOptInfo for the specified rangetable index, *	  and enter it into base_rel_array. * * Common code for build_base_rel and build_other_rel. */static RelOptInfo *make_reloptinfo(PlannerInfo *root, int relid, RelOptKind reloptkind){	RelOptInfo *rel = makeNode(RelOptInfo);	RangeTblEntry *rte = rt_fetch(relid, root->parse->rtable);	rel->reloptkind = reloptkind;	rel->relids = bms_make_singleton(relid);	rel->rows = 0;	rel->width = 0;	rel->reltargetlist = NIL;	rel->pathlist = NIL;	rel->cheapest_startup_path = NULL;	rel->cheapest_total_path = NULL;	rel->cheapest_unique_path = NULL;	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 --- set up attr range and arrays */			/* Note: 0 is included in range to support whole-row Vars */			rel->min_attr = 0;			rel->max_attr = list_length(rte->eref->colnames);			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));			break;		default:			elog(ERROR, "unrecognized RTE kind: %d",				 (int) rte->rtekind);			break;	}	/* Add the finished struct to the base_rel_array */	if (relid >= root->base_rel_array_size)	{		int			oldsize = root->base_rel_array_size;		int			newsize;		newsize = Max(oldsize * 2, relid + 1);		root->base_rel_array = (RelOptInfo **)			repalloc(root->base_rel_array, newsize * sizeof(RelOptInfo *));		MemSet(root->base_rel_array + oldsize, 0,			   (newsize - oldsize) * sizeof(RelOptInfo *));		root->base_rel_array_size = newsize;	}	root->base_rel_array[relid] = rel;	return rel;}/* * find_base_rel *	  Find a base or other relation entry, which must already exist. */RelOptInfo *find_base_rel(PlannerInfo *root, int relid){	RelOptInfo *rel;	Assert(relid > 0);	if (relid < root->base_rel_array_size)	{		rel = root->base_rel_array[relid];		if (rel)			return rel;	}	elog(ERROR, "no relation entry for relid %d", relid);	return NULL;				/* keep compiler quiet */}/* * build_join_rel_hash *	  Construct the auxiliary hash table for join relations. */static voidbuild_join_rel_hash(PlannerInfo *root){	HTAB	   *hashtab;	HASHCTL		hash_ctl;	ListCell   *l;	/* Create the hash table */	MemSet(&hash_ctl, 0, sizeof(hash_ctl));	hash_ctl.keysize = sizeof(Relids);	hash_ctl.entrysize = sizeof(JoinHashEntry);	hash_ctl.hash = bitmap_hash;	hash_ctl.match = bitmap_match;	hash_ctl.hcxt = CurrentMemoryContext;	hashtab = hash_create("JoinRelHashTable",						  256L,						  &hash_ctl,					HASH_ELEM | HASH_FUNCTION | HASH_COMPARE | HASH_CONTEXT);	/* Insert all the already-existing joinrels */	foreach(l, root->join_rel_list)	{		RelOptInfo *rel = (RelOptInfo *) lfirst(l);		JoinHashEntry *hentry;		bool		found;		hentry = (JoinHashEntry *) hash_search(hashtab,											   &(rel->relids),											   HASH_ENTER,											   &found);		Assert(!found);		hentry->join_rel = rel;	}	root->join_rel_hash = hashtab;}/* * find_join_rel *	  Returns relation entry corresponding to 'relids' (a set of RT indexes), *	  or NULL if none exists.  This is for join relations. */RelOptInfo *find_join_rel(PlannerInfo *root, Relids relids){	/*	 * Switch to using hash lookup when list grows "too long".	The threshold	 * is arbitrary and is known only here.	 */	if (!root->join_rel_hash && list_length(root->join_rel_list) > 32)		build_join_rel_hash(root);	/*	 * Use either hashtable lookup or linear search, as appropriate.	 *	 * Note: the seemingly redundant hashkey variable is used to avoid taking	 * the address of relids; unless the compiler is exceedingly smart, doing	 * so would force relids out of a register and thus probably slow down the	 * list-search case.	 */	if (root->join_rel_hash)	{		Relids		hashkey = relids;		JoinHashEntry *hentry;		hentry = (JoinHashEntry *) hash_search(root->join_rel_hash,											   &hashkey,											   HASH_FIND,											   NULL);		if (hentry)			return hentry->join_rel;	}	else	{		ListCell   *l;		foreach(l, root->join_rel_list)		{			RelOptInfo *rel = (RelOptInfo *) lfirst(l);			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...

⌨️ 快捷键说明

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