setrefs.c
来自「postgresql8.3.4源码,开源数据库」· C语言 代码 · 共 1,627 行 · 第 1/4 页
C
1,627 行
/*------------------------------------------------------------------------- * * setrefs.c * Post-processing of a completed plan tree: fix references to subplan * vars, compute regproc values for operators, etc * * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION * $PostgreSQL: pgsql/src/backend/optimizer/plan/setrefs.c,v 1.141.2.1 2008/06/17 14:51:38 tgl Exp $ * *------------------------------------------------------------------------- */#include "postgres.h"#include "catalog/pg_type.h"#include "nodes/makefuncs.h"#include "optimizer/clauses.h"#include "optimizer/planmain.h"#include "optimizer/tlist.h"#include "parser/parse_expr.h"#include "parser/parsetree.h"#include "utils/lsyscache.h"typedef struct{ Index varno; /* RT index of Var */ AttrNumber varattno; /* attr number of Var */ AttrNumber resno; /* TLE position of Var */} tlist_vinfo;typedef struct{ List *tlist; /* underlying target list */ int num_vars; /* number of plain Var tlist entries */ bool has_non_vars; /* are there non-plain-Var entries? */ /* array of num_vars entries: */ tlist_vinfo vars[1]; /* VARIABLE LENGTH ARRAY */} indexed_tlist; /* VARIABLE LENGTH STRUCT */typedef struct{ PlannerGlobal *glob; int rtoffset;} fix_scan_expr_context;typedef struct{ PlannerGlobal *glob; indexed_tlist *outer_itlist; indexed_tlist *inner_itlist; Index acceptable_rel; int rtoffset;} fix_join_expr_context;typedef struct{ PlannerGlobal *glob; indexed_tlist *subplan_itlist; int rtoffset;} fix_upper_expr_context;/* * Check if a Const node is a regclass value. We accept plain OID too, * since a regclass Const will get folded to that type if it's an argument * to oideq or similar operators. (This might result in some extraneous * values in a plan's list of relation dependencies, but the worst result * would be occasional useless replans.) */#define ISREGCLASSCONST(con) \ (((con)->consttype == REGCLASSOID || (con)->consttype == OIDOID) && \ !(con)->constisnull)#define fix_scan_list(glob, lst, rtoffset) \ ((List *) fix_scan_expr(glob, (Node *) (lst), rtoffset))static Plan *set_plan_refs(PlannerGlobal *glob, Plan *plan, int rtoffset);static Plan *set_subqueryscan_references(PlannerGlobal *glob, SubqueryScan *plan, int rtoffset);static bool trivial_subqueryscan(SubqueryScan *plan);static Node *fix_scan_expr(PlannerGlobal *glob, Node *node, int rtoffset);static Node *fix_scan_expr_mutator(Node *node, fix_scan_expr_context *context);static bool fix_scan_expr_walker(Node *node, fix_scan_expr_context *context);static void set_join_references(PlannerGlobal *glob, Join *join, int rtoffset);static void set_inner_join_references(PlannerGlobal *glob, Plan *inner_plan, indexed_tlist *outer_itlist);static void set_upper_references(PlannerGlobal *glob, Plan *plan, int rtoffset);static void set_dummy_tlist_references(Plan *plan, int rtoffset);static indexed_tlist *build_tlist_index(List *tlist);static Var *search_indexed_tlist_for_var(Var *var, indexed_tlist *itlist, Index newvarno, int rtoffset);static Var *search_indexed_tlist_for_non_var(Node *node, indexed_tlist *itlist, Index newvarno);static List *fix_join_expr(PlannerGlobal *glob, List *clauses, indexed_tlist *outer_itlist, indexed_tlist *inner_itlist, Index acceptable_rel, int rtoffset);static Node *fix_join_expr_mutator(Node *node, fix_join_expr_context *context);static Node *fix_upper_expr(PlannerGlobal *glob, Node *node, indexed_tlist *subplan_itlist, int rtoffset);static Node *fix_upper_expr_mutator(Node *node, fix_upper_expr_context *context);static bool fix_opfuncids_walker(Node *node, void *context);/***************************************************************************** * * SUBPLAN REFERENCES * *****************************************************************************//* * set_plan_references * * This is the final processing pass of the planner/optimizer. The plan * tree is complete; we just have to adjust some representational details * for the convenience of the executor: * * 1. We flatten the various subquery rangetables into a single list, and * zero out RangeTblEntry fields that are not useful to the executor. * * 2. We adjust Vars in scan nodes to be consistent with the flat rangetable. * * 3. We adjust Vars in upper plan nodes to refer to the outputs of their * subplans. * * 4. We compute regproc OIDs for operators (ie, we look up the function * that implements each op). * * 5. We create a list of OIDs of relations that the plan depends on. * This will be used by plancache.c to drive invalidation of cached plans. * (Someday we might want to generalize this to include other types of * objects, but for now tracking relations seems to solve most problems.) * * We also perform one final optimization step, which is to delete * SubqueryScan plan nodes that aren't doing anything useful (ie, have * no qual and a no-op targetlist). The reason for doing this last is that * it can't readily be done before set_plan_references, because it would * break set_upper_references: the Vars in the subquery's top tlist * wouldn't match up with the Vars in the outer plan tree. The SubqueryScan * serves a necessary function as a buffer between outer query and subquery * variable numbering ... but after we've flattened the rangetable this is * no longer a problem, since then there's only one rtindex namespace. * * set_plan_references recursively traverses the whole plan tree. * * Inputs: * glob: global data for planner run * plan: the topmost node of the plan * rtable: the rangetable for the current subquery * * The return value is normally the same Plan node passed in, but can be * different when the passed-in Plan is a SubqueryScan we decide isn't needed. * * The flattened rangetable entries are appended to glob->finalrtable, and * the list of relation OIDs is appended to glob->relationOids. * * Notice that we modify Plan nodes in-place, but use expression_tree_mutator * to process targetlist and qual expressions. We can assume that the Plan * nodes were just built by the planner and are not multiply referenced, but * it's not so safe to assume that for expression tree nodes. */Plan *set_plan_references(PlannerGlobal *glob, Plan *plan, List *rtable){ int rtoffset = list_length(glob->finalrtable); ListCell *lc; /* * In the flat rangetable, we zero out substructure pointers that are not * needed by the executor; this reduces the storage space and copying cost * for cached plans. We keep only the alias and eref Alias fields, which * are needed by EXPLAIN. */ foreach(lc, rtable) { RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc); RangeTblEntry *newrte; /* flat copy to duplicate all the scalar fields */ newrte = (RangeTblEntry *) palloc(sizeof(RangeTblEntry)); memcpy(newrte, rte, sizeof(RangeTblEntry)); /* zap unneeded sub-structure */ newrte->subquery = NULL; newrte->funcexpr = NULL; newrte->funccoltypes = NIL; newrte->funccoltypmods = NIL; newrte->values_lists = NIL; newrte->joinaliasvars = NIL; glob->finalrtable = lappend(glob->finalrtable, newrte); /* * If it's a plain relation RTE, add the table to relationOids. * * We do this even though the RTE might be unreferenced in the plan * tree; this would correspond to cases such as views that were * expanded, child tables that were eliminated by constraint * exclusion, etc. Schema invalidation on such a rel must still force * rebuilding of the plan. * * Note we don't bother to avoid duplicate list entries. We could, * but it would probably cost more cycles than it would save. */ if (newrte->rtekind == RTE_RELATION) glob->relationOids = lappend_oid(glob->relationOids, newrte->relid); } /* Now fix the Plan tree */ return set_plan_refs(glob, plan, rtoffset);}/* * set_plan_refs: recurse through the Plan nodes of a single subquery level */static Plan *set_plan_refs(PlannerGlobal *glob, Plan *plan, int rtoffset){ ListCell *l; if (plan == NULL) return NULL; /* * Plan-type-specific fixes */ switch (nodeTag(plan)) { case T_SeqScan: { SeqScan *splan = (SeqScan *) plan; splan->scanrelid += rtoffset; splan->plan.targetlist = fix_scan_list(glob, splan->plan.targetlist, rtoffset); splan->plan.qual = fix_scan_list(glob, splan->plan.qual, rtoffset); } break; case T_IndexScan: { IndexScan *splan = (IndexScan *) plan; splan->scan.scanrelid += rtoffset; splan->scan.plan.targetlist = fix_scan_list(glob, splan->scan.plan.targetlist, rtoffset); splan->scan.plan.qual = fix_scan_list(glob, splan->scan.plan.qual, rtoffset); splan->indexqual = fix_scan_list(glob, splan->indexqual, rtoffset); splan->indexqualorig = fix_scan_list(glob, splan->indexqualorig, rtoffset); } break; case T_BitmapIndexScan: { BitmapIndexScan *splan = (BitmapIndexScan *) plan; splan->scan.scanrelid += rtoffset; /* no need to fix targetlist and qual */ Assert(splan->scan.plan.targetlist == NIL); Assert(splan->scan.plan.qual == NIL); splan->indexqual = fix_scan_list(glob, splan->indexqual, rtoffset); splan->indexqualorig = fix_scan_list(glob, splan->indexqualorig, rtoffset); } break; case T_BitmapHeapScan: { BitmapHeapScan *splan = (BitmapHeapScan *) plan; splan->scan.scanrelid += rtoffset; splan->scan.plan.targetlist = fix_scan_list(glob, splan->scan.plan.targetlist, rtoffset); splan->scan.plan.qual = fix_scan_list(glob, splan->scan.plan.qual, rtoffset); splan->bitmapqualorig = fix_scan_list(glob, splan->bitmapqualorig, rtoffset); } break; case T_TidScan: { TidScan *splan = (TidScan *) plan; splan->scan.scanrelid += rtoffset; splan->scan.plan.targetlist = fix_scan_list(glob, splan->scan.plan.targetlist, rtoffset); splan->scan.plan.qual = fix_scan_list(glob, splan->scan.plan.qual, rtoffset); splan->tidquals = fix_scan_list(glob, splan->tidquals, rtoffset); } break; case T_SubqueryScan: /* Needs special treatment, see comments below */ return set_subqueryscan_references(glob, (SubqueryScan *) plan, rtoffset); case T_FunctionScan: { FunctionScan *splan = (FunctionScan *) plan; splan->scan.scanrelid += rtoffset; splan->scan.plan.targetlist = fix_scan_list(glob, splan->scan.plan.targetlist, rtoffset); splan->scan.plan.qual = fix_scan_list(glob, splan->scan.plan.qual, rtoffset); splan->funcexpr = fix_scan_expr(glob, splan->funcexpr, rtoffset); } break; case T_ValuesScan: { ValuesScan *splan = (ValuesScan *) plan; splan->scan.scanrelid += rtoffset; splan->scan.plan.targetlist = fix_scan_list(glob, splan->scan.plan.targetlist, rtoffset); splan->scan.plan.qual = fix_scan_list(glob, splan->scan.plan.qual, rtoffset); splan->values_lists = fix_scan_list(glob, splan->values_lists, rtoffset); } break; case T_NestLoop: case T_MergeJoin: case T_HashJoin: set_join_references(glob, (Join *) plan, rtoffset); break; case T_Hash: case T_Material: case T_Sort: case T_Unique: case T_SetOp: /* * These plan types don't actually bother to evaluate their * targetlists, because they just return their unmodified input * tuples. Even though the targetlist won't be used by the * executor, we fix it up for possible use by EXPLAIN (not to * mention ease of debugging --- wrong varnos are very confusing). */ set_dummy_tlist_references(plan, rtoffset); /* * Since these plan types don't check quals either, we should not * find any qual expression attached to them. */ Assert(plan->qual == NIL); break; case T_Limit: { Limit *splan = (Limit *) plan; /* * Like the plan types above, Limit doesn't evaluate its tlist * or quals. It does have live expressions for limit/offset, * however; and those cannot contain subplan variable refs, so * fix_scan_expr works for them. */ set_dummy_tlist_references(plan, rtoffset); Assert(splan->plan.qual == NIL); splan->limitOffset = fix_scan_expr(glob, splan->limitOffset, rtoffset); splan->limitCount = fix_scan_expr(glob, splan->limitCount, rtoffset); } break; case T_Agg: case T_Group: set_upper_references(glob, plan, rtoffset); break; case T_Result: { Result *splan = (Result *) plan; /* * Result may or may not have a subplan; if not, it's more * like a scan node than an upper node. */ if (splan->plan.lefttree != NULL) set_upper_references(glob, plan, rtoffset); else { splan->plan.targetlist = fix_scan_list(glob, splan->plan.targetlist, rtoffset); splan->plan.qual = fix_scan_list(glob, splan->plan.qual, rtoffset); } /* resconstantqual can't contain any subplan variable refs */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?