📄 subselect.c
字号:
{ SubPlan *subplan = (SubPlan *) ((Expr *) node)->oper; List *lst; /* Add subplan to subplans list */ results->subplans = lappend(results->subplans, subplan); /* Check extParam list for params to add to paramids */ foreach(lst, subplan->plan->extParam) { int paramid = lfirsti(lst); Var *var = nth(paramid, PlannerParamVar); /* note varlevelsup is absolute level number */ if (var->varlevelsup < PlannerQueryLevel && ! intMember(paramid, results->paramids)) results->paramids = lconsi(paramid, results->paramids); } /* XXX We do NOT allow expression_tree_walker to examine the args * passed to the subplan. Is that correct??? It's what the * old code did, but it seems mighty bogus... tgl 7/14/99 */ return false; /* don't recurse into subplan args */ } return expression_tree_walker(node, finalize_primnode_walker, (void *) results);}/* Replace correlation vars (uplevel vars) with Params. *//* XXX should replace this with use of a generalized tree rebuilder, * designed along the same lines as expression_tree_walker. * Not done yet. */Node *SS_replace_correlation_vars(Node *expr){ if (expr == NULL) return NULL; if (IsA(expr, Var)) { if (((Var *) expr)->varlevelsup > 0) expr = (Node *) _replace_var((Var *) expr); } else if (single_node(expr)) return expr; else if (IsA(expr, List)) { List *le; foreach(le, (List *) expr) lfirst(le) = SS_replace_correlation_vars((Node *) lfirst(le)); } else if (IsA(expr, Expr)) { /* XXX do we need to do anything special with subplans? */ ((Expr *) expr)->args = (List *) SS_replace_correlation_vars((Node *) ((Expr *) expr)->args); } else if (IsA(expr, Aggref)) ((Aggref *) expr)->target = SS_replace_correlation_vars(((Aggref *) expr)->target); else if (IsA(expr, Iter)) ((Iter *) expr)->iterexpr = SS_replace_correlation_vars(((Iter *) expr)->iterexpr); else if (IsA(expr, ArrayRef)) { ((ArrayRef *) expr)->refupperindexpr = (List *) SS_replace_correlation_vars((Node *) ((ArrayRef *) expr)->refupperindexpr); ((ArrayRef *) expr)->reflowerindexpr = (List *) SS_replace_correlation_vars((Node *) ((ArrayRef *) expr)->reflowerindexpr); ((ArrayRef *) expr)->refexpr = SS_replace_correlation_vars(((ArrayRef *) expr)->refexpr); ((ArrayRef *) expr)->refassgnexpr = SS_replace_correlation_vars(((ArrayRef *) expr)->refassgnexpr); } else if (IsA(expr, CaseExpr)) { CaseExpr *caseexpr = (CaseExpr *) expr; List *le; foreach(le, caseexpr->args) { CaseWhen *when = (CaseWhen *) lfirst(le); Assert(IsA(when, CaseWhen)); when->expr = SS_replace_correlation_vars(when->expr); when->result = SS_replace_correlation_vars(when->result); } /* caseexpr->arg should be null, but we'll check it anyway */ caseexpr->arg = SS_replace_correlation_vars(caseexpr->arg); caseexpr->defresult = SS_replace_correlation_vars(caseexpr->defresult); } else if (IsA(expr, TargetEntry)) ((TargetEntry *) expr)->expr = SS_replace_correlation_vars(((TargetEntry *) expr)->expr); else if (IsA(expr, SubLink)) { List *le; foreach(le, ((SubLink *) expr)->oper) /* left sides only */ { List *oparg = ((Expr *) lfirst(le))->args; lfirst(oparg) = (List *) SS_replace_correlation_vars((Node *) lfirst(oparg)); } ((SubLink *) expr)->lefthand = (List *) SS_replace_correlation_vars((Node *) ((SubLink *) expr)->lefthand); } else elog(ERROR, "SS_replace_correlation_vars: can't handle node %d", nodeTag(expr)); return expr;}/* Replace sublinks by subplans in the given expression *//* XXX should replace this with use of a generalized tree rebuilder, * designed along the same lines as expression_tree_walker. * Not done yet. */Node *SS_process_sublinks(Node *expr){ if (expr == NULL) return NULL; if (IsA(expr, SubLink)) { expr = _make_subplan((SubLink *) expr); } else if (single_node(expr)) return expr; else if (IsA(expr, List)) { List *le; foreach(le, (List *) expr) lfirst(le) = SS_process_sublinks((Node *) lfirst(le)); } else if (IsA(expr, Expr)) { /* We should never see a subplan node here, since this is the * routine that makes 'em in the first place. No need to check. */ ((Expr *) expr)->args = (List *) SS_process_sublinks((Node *) ((Expr *) expr)->args); } else if (IsA(expr, Aggref)) ((Aggref *) expr)->target = SS_process_sublinks(((Aggref *) expr)->target); else if (IsA(expr, Iter)) ((Iter *) expr)->iterexpr = SS_process_sublinks(((Iter *) expr)->iterexpr); else if (IsA(expr, ArrayRef)) { ((ArrayRef *) expr)->refupperindexpr = (List *) SS_process_sublinks((Node *) ((ArrayRef *) expr)->refupperindexpr); ((ArrayRef *) expr)->reflowerindexpr = (List *) SS_process_sublinks((Node *) ((ArrayRef *) expr)->reflowerindexpr); ((ArrayRef *) expr)->refexpr = SS_process_sublinks(((ArrayRef *) expr)->refexpr); ((ArrayRef *) expr)->refassgnexpr = SS_process_sublinks(((ArrayRef *) expr)->refassgnexpr); } else if (IsA(expr, CaseExpr)) { CaseExpr *caseexpr = (CaseExpr *) expr; List *le; foreach(le, caseexpr->args) { CaseWhen *when = (CaseWhen *) lfirst(le); Assert(IsA(when, CaseWhen)); when->expr = SS_process_sublinks(when->expr); when->result = SS_process_sublinks(when->result); } /* caseexpr->arg should be null, but we'll check it anyway */ caseexpr->arg = SS_process_sublinks(caseexpr->arg); caseexpr->defresult = SS_process_sublinks(caseexpr->defresult); } else elog(ERROR, "SS_process_sublinks: can't handle node %d", nodeTag(expr)); return expr;}List *SS_finalize_plan(Plan *plan){ List *extParam = NIL; List *locParam = NIL; finalize_primnode_results results; List *lst; if (plan == NULL) return NULL; /* Find params in targetlist, make sure there are no subplans there */ finalize_primnode((Node *) plan->targetlist, &results); Assert(results.subplans == NIL); /* From here on, we invoke finalize_primnode_walker not finalize_primnode, * so that results.paramids lists are automatically merged together and * we don't have to do it the hard way. But when recursing to self, * we do have to merge the lists. Oh well. */ switch (nodeTag(plan)) { case T_Result: finalize_primnode_walker(((Result *) plan)->resconstantqual, &results); /* results.subplans is NOT necessarily empty here ... */ break; case T_Append: foreach(lst, ((Append *) plan)->appendplans) results.paramids = set_unioni(results.paramids, SS_finalize_plan((Plan *) lfirst(lst))); break; case T_IndexScan: finalize_primnode_walker((Node *) ((IndexScan *) plan)->indxqual, &results); Assert(results.subplans == NIL); break; case T_MergeJoin: finalize_primnode_walker((Node *) ((MergeJoin *) plan)->mergeclauses, &results); Assert(results.subplans == NIL); break; case T_HashJoin: finalize_primnode_walker((Node *) ((HashJoin *) plan)->hashclauses, &results); Assert(results.subplans == NIL); break; case T_Hash: finalize_primnode_walker((Node *) ((Hash *) plan)->hashkey, &results); Assert(results.subplans == NIL); break; case T_Agg: finalize_primnode_walker((Node *) ((Agg *) plan)->aggs, &results); Assert(results.subplans == NIL); break; case T_SeqScan: case T_NestLoop: case T_Material: case T_Sort: case T_Unique: case T_Group: break; default: elog(ERROR, "SS_finalize_plan: node %d unsupported", nodeTag(plan)); return NULL; } finalize_primnode_walker((Node *) plan->qual, &results); /* subplans are OK in the qual... */ results.paramids = set_unioni(results.paramids, SS_finalize_plan(plan->lefttree)); results.paramids = set_unioni(results.paramids, SS_finalize_plan(plan->righttree)); /* Now we have all the paramids and subplans */ foreach(lst, results.paramids) { Var *var = nth(lfirsti(lst), PlannerParamVar); /* note varlevelsup is absolute level number */ if (var->varlevelsup < PlannerQueryLevel) extParam = lappendi(extParam, lfirsti(lst)); else if (var->varlevelsup > PlannerQueryLevel) elog(ERROR, "SS_finalize_plan: plan shouldn't reference subplan's variable"); else { Assert(var->varno == 0 && var->varattno == 0); locParam = lappendi(locParam, lfirsti(lst)); } } plan->extParam = extParam; plan->locParam = locParam; plan->subPlan = results.subplans; return results.paramids;}/* Construct a list of all subplans found within the given node tree */static bool SS_pull_subplan_walker(Node *node, List **listptr);List *SS_pull_subplan(Node *expr){ List *result = NIL; SS_pull_subplan_walker(expr, &result); return result;}static boolSS_pull_subplan_walker(Node *node, List **listptr){ if (node == NULL) return false; if (is_subplan(node)) { *listptr = lappend(*listptr, ((Expr *) node)->oper); /* XXX original code did not examine args to subplan, is this right? */ return false; } return expression_tree_walker(node, SS_pull_subplan_walker, (void *) listptr);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -