📄 setrefs.c
字号:
TargetEntry *ctle = (TargetEntry *) lfirst(lc); Var *var = (Var *) ptle->expr; if (ptle->resjunk != ctle->resjunk) return false; /* tlist doesn't match junk status */ if (!var || !IsA(var, Var)) return false; /* tlist item not a Var */ Assert(var->varno == plan->scan.scanrelid); Assert(var->varlevelsup == 0); if (var->varattno != attrno) return false; /* out of order */ attrno++; } return true;}/* * adjust_plan_varnos * Offset varnos and other rangetable indexes in a plan tree by rtoffset. */static voidadjust_plan_varnos(Plan *plan, int rtoffset){ ListCell *l; if (plan == NULL) return; /* * Plan-type-specific fixes */ switch (nodeTag(plan)) { case T_SeqScan: ((SeqScan *) plan)->scanrelid += rtoffset; adjust_expr_varnos((Node *) plan->targetlist, rtoffset); adjust_expr_varnos((Node *) plan->qual, rtoffset); break; case T_IndexScan: ((IndexScan *) plan)->scan.scanrelid += rtoffset; adjust_expr_varnos((Node *) plan->targetlist, rtoffset); adjust_expr_varnos((Node *) plan->qual, rtoffset); adjust_expr_varnos((Node *) ((IndexScan *) plan)->indexqual, rtoffset); adjust_expr_varnos((Node *) ((IndexScan *) plan)->indexqualorig, rtoffset); break; case T_BitmapIndexScan: ((BitmapIndexScan *) plan)->scan.scanrelid += rtoffset; /* no need to fix targetlist and qual */ Assert(plan->targetlist == NIL); Assert(plan->qual == NIL); adjust_expr_varnos((Node *) ((BitmapIndexScan *) plan)->indexqual, rtoffset); adjust_expr_varnos((Node *) ((BitmapIndexScan *) plan)->indexqualorig, rtoffset); break; case T_BitmapHeapScan: ((BitmapHeapScan *) plan)->scan.scanrelid += rtoffset; adjust_expr_varnos((Node *) plan->targetlist, rtoffset); adjust_expr_varnos((Node *) plan->qual, rtoffset); adjust_expr_varnos((Node *) ((BitmapHeapScan *) plan)->bitmapqualorig, rtoffset); break; case T_TidScan: ((TidScan *) plan)->scan.scanrelid += rtoffset; adjust_expr_varnos((Node *) plan->targetlist, rtoffset); adjust_expr_varnos((Node *) plan->qual, rtoffset); adjust_expr_varnos((Node *) ((TidScan *) plan)->tideval, rtoffset); break; case T_SubqueryScan: ((SubqueryScan *) plan)->scan.scanrelid += rtoffset; adjust_expr_varnos((Node *) plan->targetlist, rtoffset); adjust_expr_varnos((Node *) plan->qual, rtoffset); /* we should not recurse into the subquery! */ break; case T_FunctionScan: ((FunctionScan *) plan)->scan.scanrelid += rtoffset; adjust_expr_varnos((Node *) plan->targetlist, rtoffset); adjust_expr_varnos((Node *) plan->qual, rtoffset); /* rte was already fixed by set_subqueryscan_references */ break; case T_NestLoop: adjust_expr_varnos((Node *) plan->targetlist, rtoffset); adjust_expr_varnos((Node *) plan->qual, rtoffset); adjust_expr_varnos((Node *) ((Join *) plan)->joinqual, rtoffset); break; case T_MergeJoin: adjust_expr_varnos((Node *) plan->targetlist, rtoffset); adjust_expr_varnos((Node *) plan->qual, rtoffset); adjust_expr_varnos((Node *) ((Join *) plan)->joinqual, rtoffset); adjust_expr_varnos((Node *) ((MergeJoin *) plan)->mergeclauses, rtoffset); break; case T_HashJoin: adjust_expr_varnos((Node *) plan->targetlist, rtoffset); adjust_expr_varnos((Node *) plan->qual, rtoffset); adjust_expr_varnos((Node *) ((Join *) plan)->joinqual, rtoffset); adjust_expr_varnos((Node *) ((HashJoin *) plan)->hashclauses, rtoffset); break; case T_Hash: case T_Material: case T_Sort: case T_Unique: case T_SetOp: /* * 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). */ adjust_expr_varnos((Node *) plan->targetlist, rtoffset); Assert(plan->qual == NIL); break; case T_Limit: /* * Like the plan types above, Limit doesn't evaluate its tlist or * quals. It does have live expressions for limit/offset, * however. */ adjust_expr_varnos((Node *) plan->targetlist, rtoffset); Assert(plan->qual == NIL); adjust_expr_varnos(((Limit *) plan)->limitOffset, rtoffset); adjust_expr_varnos(((Limit *) plan)->limitCount, rtoffset); break; case T_Agg: case T_Group: adjust_expr_varnos((Node *) plan->targetlist, rtoffset); adjust_expr_varnos((Node *) plan->qual, rtoffset); break; case T_Result: adjust_expr_varnos((Node *) plan->targetlist, rtoffset); adjust_expr_varnos((Node *) plan->qual, rtoffset); adjust_expr_varnos(((Result *) plan)->resconstantqual, rtoffset); break; case T_Append: adjust_expr_varnos((Node *) plan->targetlist, rtoffset); Assert(plan->qual == NIL); foreach(l, ((Append *) plan)->appendplans) adjust_plan_varnos((Plan *) lfirst(l), rtoffset); break; case T_BitmapAnd: /* BitmapAnd works like Append, but has no tlist */ Assert(plan->targetlist == NIL); Assert(plan->qual == NIL); foreach(l, ((BitmapAnd *) plan)->bitmapplans) adjust_plan_varnos((Plan *) lfirst(l), rtoffset); break; case T_BitmapOr: /* BitmapOr works like Append, but has no tlist */ Assert(plan->targetlist == NIL); Assert(plan->qual == NIL); foreach(l, ((BitmapOr *) plan)->bitmapplans) adjust_plan_varnos((Plan *) lfirst(l), rtoffset); break; default: elog(ERROR, "unrecognized node type: %d", (int) nodeTag(plan)); break; } /* * Now recurse into child plans. * * We don't need to (and in fact mustn't) recurse into subqueries, so no * need to examine initPlan list. */ adjust_plan_varnos(plan->lefttree, rtoffset); adjust_plan_varnos(plan->righttree, rtoffset);}/* * adjust_expr_varnos * Offset varnos of Vars in an expression by rtoffset. * * This is different from the rewriter's OffsetVarNodes in that it has to * work on an already-planned expression tree; in particular, we should not * disturb INNER and OUTER references. On the other hand, we don't have to * recurse into subqueries nor deal with outer-level Vars, so it's pretty * simple. */static voidadjust_expr_varnos(Node *node, int rtoffset){ /* This tree walk requires no special setup, so away we go... */ adjust_expr_varnos_walker(node, &rtoffset);}static booladjust_expr_varnos_walker(Node *node, int *context){ if (node == NULL) return false; if (IsA(node, Var)) { Var *var = (Var *) node; Assert(var->varlevelsup == 0); if (var->varno > 0 && var->varno != INNER && var->varno != OUTER) var->varno += *context; if (var->varnoold > 0) var->varnoold += *context; return false; } return expression_tree_walker(node, adjust_expr_varnos_walker, (void *) context);}/* * fix_expr_references * Do final cleanup on expressions (targetlists or quals). * * This consists of looking up operator opcode info for OpExpr nodes * and recursively performing set_plan_references on subplans. * * The Plan argument is currently unused, but might be needed again someday. */static voidfix_expr_references(Plan *plan, Node *node){ /* This tree walk requires no special setup, so away we go... */ fix_expr_references_walker(node, NULL);}static boolfix_expr_references_walker(Node *node, void *context){ if (node == NULL) return false; if (IsA(node, OpExpr)) set_opfuncid((OpExpr *) node); else if (IsA(node, DistinctExpr)) set_opfuncid((OpExpr *) node); /* rely on struct equivalence */ else if (IsA(node, ScalarArrayOpExpr)) set_sa_opfuncid((ScalarArrayOpExpr *) node); else if (IsA(node, NullIfExpr)) set_opfuncid((OpExpr *) node); /* rely on struct equivalence */ else if (IsA(node, SubPlan)) { SubPlan *sp = (SubPlan *) node; sp->plan = set_plan_references(sp->plan, sp->rtable); } return expression_tree_walker(node, fix_expr_references_walker, context);}/* * set_join_references * Modifies the target list and quals of a join node to reference its * subplans, by setting the varnos to OUTER or INNER and setting attno * values to the result domain number of either the corresponding outer * or inner join tuple item. * * In the case of a nestloop with inner indexscan, we will also need to * apply the same transformation to any outer vars appearing in the * quals of the child indexscan. set_inner_join_references does that. * * 'join' is a join plan node * 'rtable' is the associated range table */static voidset_join_references(Join *join, List *rtable){ Plan *outer_plan = join->plan.lefttree; Plan *inner_plan = join->plan.righttree; indexed_tlist *outer_itlist; indexed_tlist *inner_itlist; outer_itlist = build_tlist_index(outer_plan->targetlist); inner_itlist = build_tlist_index(inner_plan->targetlist); /* All join plans have tlist, qual, and joinqual */ join->plan.targetlist = join_references(join->plan.targetlist, rtable, outer_itlist, inner_itlist, (Index) 0); join->plan.qual = join_references(join->plan.qual, rtable, outer_itlist, inner_itlist, (Index) 0); join->joinqual = join_references(join->joinqual, rtable, outer_itlist, inner_itlist, (Index) 0); /* Now do join-type-specific stuff */ if (IsA(join, NestLoop)) { /* This processing is split out to handle possible recursion */ set_inner_join_references(inner_plan, rtable, outer_itlist); } else if (IsA(join, MergeJoin)) { MergeJoin *mj = (MergeJoin *) join; mj->mergeclauses = join_references(mj->mergeclauses, rtable, outer_itlist, inner_itlist, (Index) 0); } else if (IsA(join, HashJoin)) { HashJoin *hj = (HashJoin *) join; hj->hashclauses = join_references(hj->hashclauses, rtable, outer_itlist, inner_itlist, (Index) 0); } pfree(outer_itlist); pfree(inner_itlist);}/* * set_inner_join_references * Handle join references appearing in an inner indexscan's quals * * To handle bitmap-scan plan trees, we have to be able to recurse down * to the bottom BitmapIndexScan nodes, so this is split out as a separate * function. */static voidset_inner_join_references(Plan *inner_plan, List *rtable, indexed_tlist *outer_itlist){ if (IsA(inner_plan, IndexScan)) { /* * An index is being used to reduce the number of tuples scanned in * the inner relation. If there are join clauses being used with the * index, we must update their outer-rel var nodes to refer to the * outer side of the join. */ IndexScan *innerscan = (IndexScan *) inner_plan; List *indexqualorig = innerscan->indexqualorig; /* No work needed if indexqual refers only to its own rel... */ if (NumRelids((Node *) indexqualorig) > 1) { Index innerrel = innerscan->scan.scanrelid; /* only refs to outer vars get changed in the inner qual */ innerscan->indexqualorig = join_references(indexqualorig, rtable, outer_itlist, NULL, innerrel); innerscan->indexqual = join_references(innerscan->indexqual, rtable, outer_itlist, NULL, innerrel); /* * We must fix the inner qpqual too, if it has join clauses (this * could happen if special operators are involved: some indexquals * may get rechecked as qpquals). */ if (NumRelids((Node *) inner_plan->qual) > 1) inner_plan->qual = join_references(inner_plan->qual, rtable, outer_itlist, NULL, innerrel); } } else if (IsA(inner_plan, BitmapIndexScan)) { /* * Same, but index is being used within a bitmap plan. */ BitmapIndexScan *innerscan = (BitmapIndexScan *) inner_plan; List *indexqualorig = innerscan->indexqualorig; /* No work needed if indexqual refers only to its own rel... */ if (NumRelids((Node *) indexqualorig) > 1) { Index innerrel = innerscan->scan.scanrelid; /* only refs to outer vars get changed in the inner qual */ innerscan->indexqualorig = join_references(indexqualorig, rtable, outer_itlist, NULL, innerrel); innerscan->indexqual = join_references(innerscan->indexqual, rtable, outer_itlist, NULL, innerrel); /* no need to fix inner qpqual */ Assert(inner_plan->qual == NIL); } } else if (IsA(inner_plan, BitmapHeapScan)) { /* * The inner side is a bitmap scan plan. Fix the top node, and * recurse to get the lower nodes. * * Note: create_bitmap_scan_plan removes clauses from bitmapqualorig * if they are duplicated in qpqual, so must test these independently. */ BitmapHeapScan *innerscan = (BitmapHeapScan *) inner_plan; Index innerrel = innerscan->scan.scanrelid; List *bitmapqualorig = innerscan->bitmapqualorig; /* only refs to outer vars get changed in the inner qual */ if (NumRelids((Node *) bitmapqualorig) > 1) innerscan->bitmapqualorig = join_references(bitmapqualorig, rtable, outer_itlist, NULL, innerrel); /* * We must fix the inner qpqual too, if it has join clauses (this * could happen if special operators are involved: some indexquals may * get rechecked as qpquals). */ if (NumRelids((Node *) inner_plan->qual) > 1) inner_plan->qual = join_references(inner_plan->qual, rtable, outer_itlist, NULL, innerrel); /* Now recurse */ set_inner_join_references(inner_plan->lefttree,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -