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 + -
显示快捷键?