📄 createplan.c
字号:
if (!tlist_member(lfirst(k), tlist)) break; } freeList(exprvars); if (!k) break; /* found usable expression */ } if (!j) elog(ERROR, "could not find pathkey item to sort"); /* * Do we need to insert a Result node? * * Currently, the only non-projection-capable plan types we can * see here are Append and Unique. */ if (IsA(lefttree, Append) || IsA(lefttree, Unique)) { tlist = copyObject(tlist); lefttree = (Plan *) make_result(tlist, NULL, lefttree); } /* * Add resjunk entry to input's tlist */ resdom = makeResdom(length(tlist) + 1, exprType(pathkey->key), exprTypmod(pathkey->key), NULL, true); tlist = lappend(tlist, makeTargetEntry(resdom, (Expr *) pathkey->key)); lefttree->targetlist = tlist; /* just in case NIL before */ } /* * The column might already be selected as a sort key, if the * pathkeys contain duplicate entries. (This can happen in * scenarios where multiple mergejoinable clauses mention the same * var, for example.) So enter it only once in the sort arrays. */ numsortkeys = add_sort_column(resdom->resno, pathkey->sortop, numsortkeys, sortColIdx, sortOperators); } Assert(numsortkeys > 0); /* Give Sort node its own copy of the tlist (still necessary?) */ sort_tlist = copyObject(tlist); return make_sort(root, sort_tlist, lefttree, numsortkeys, sortColIdx, sortOperators);}/* * make_sort_from_sortclauses * Create sort plan to sort according to given sortclauses * * 'tlist' is the targetlist * 'lefttree' is the node which yields input tuples * 'sortcls' is a list of SortClauses */Sort *make_sort_from_sortclauses(Query *root, List *tlist, Plan *lefttree, List *sortcls){ List *sort_tlist; List *i; int numsortkeys; AttrNumber *sortColIdx; Oid *sortOperators; /* We will need at most length(sortcls) sort columns; possibly less */ numsortkeys = length(sortcls); sortColIdx = (AttrNumber *) palloc(numsortkeys * sizeof(AttrNumber)); sortOperators = (Oid *) palloc(numsortkeys * sizeof(Oid)); numsortkeys = 0; foreach(i, sortcls) { SortClause *sortcl = (SortClause *) lfirst(i); TargetEntry *tle = get_sortgroupclause_tle(sortcl, tlist); Resdom *resdom = tle->resdom; /* * Check for the possibility of duplicate order-by clauses --- the * parser should have removed 'em, but no point in sorting * redundantly. */ numsortkeys = add_sort_column(resdom->resno, sortcl->sortop, numsortkeys, sortColIdx, sortOperators); } Assert(numsortkeys > 0); /* Give Sort node its own copy of the tlist (still necessary?) */ sort_tlist = copyObject(tlist); return make_sort(root, sort_tlist, lefttree, numsortkeys, sortColIdx, sortOperators);}/* * make_sort_from_groupcols * Create sort plan to sort based on grouping columns * * 'groupcls' is the list of GroupClauses * 'grpColIdx' gives the column numbers to use * * This might look like it could be merged with make_sort_from_sortclauses, * but presently we *must* use the grpColIdx[] array to locate sort columns, * because the child plan's tlist is not marked with ressortgroupref info * appropriate to the grouping node. So, only the sortop is used from the * GroupClause entries. */Sort *make_sort_from_groupcols(Query *root, List *groupcls, AttrNumber *grpColIdx, Plan *lefttree){ List *sub_tlist = lefttree->targetlist; List *sort_tlist; int grpno = 0; List *i; int numsortkeys; AttrNumber *sortColIdx; Oid *sortOperators; /* We will need at most length(groupcls) sort columns; possibly less */ numsortkeys = length(groupcls); sortColIdx = (AttrNumber *) palloc(numsortkeys * sizeof(AttrNumber)); sortOperators = (Oid *) palloc(numsortkeys * sizeof(Oid)); numsortkeys = 0; foreach(i, groupcls) { GroupClause *grpcl = (GroupClause *) lfirst(i); TargetEntry *tle = get_tle_by_resno(sub_tlist, grpColIdx[grpno]); Resdom *resdom = tle->resdom; /* * Check for the possibility of duplicate group-by clauses --- the * parser should have removed 'em, but no point in sorting * redundantly. */ numsortkeys = add_sort_column(resdom->resno, grpcl->sortop, numsortkeys, sortColIdx, sortOperators); grpno++; } Assert(numsortkeys > 0); /* Give Sort node its own copy of the tlist (still necessary?) */ sort_tlist = copyObject(sub_tlist); return make_sort(root, sort_tlist, lefttree, numsortkeys, sortColIdx, sortOperators);}Material *make_material(List *tlist, Plan *lefttree){ Material *node = makeNode(Material); Plan *plan = &node->plan; /* cost should be inserted by caller */ plan->targetlist = tlist; plan->qual = NIL; plan->lefttree = lefttree; plan->righttree = NULL; return node;}/* * materialize_finished_plan: stick a Material node atop a completed plan * * There are a couple of places where we want to attach a Material node * after completion of subquery_planner(). This currently requires hackery. * Since subquery_planner has already run SS_finalize_plan on the subplan * tree, we have to kluge up parameter lists for the Material node. * Possibly this could be fixed by postponing SS_finalize_plan processing * until setrefs.c is run? */Plan *materialize_finished_plan(Plan *subplan){ Plan *matplan; Path matpath; /* dummy for result of cost_material */ matplan = (Plan *) make_material(subplan->targetlist, subplan); /* Set cost data */ cost_material(&matpath, subplan->total_cost, subplan->plan_rows, subplan->plan_width); matplan->startup_cost = matpath.startup_cost; matplan->total_cost = matpath.total_cost; matplan->plan_rows = subplan->plan_rows; matplan->plan_width = subplan->plan_width; /* parameter kluge --- see comments above */ matplan->extParam = bms_copy(subplan->extParam); matplan->allParam = bms_copy(subplan->allParam); return matplan;}Agg *make_agg(Query *root, List *tlist, List *qual, AggStrategy aggstrategy, int numGroupCols, AttrNumber *grpColIdx, long numGroups, int numAggs, Plan *lefttree){ Agg *node = makeNode(Agg); Plan *plan = &node->plan; Path agg_path; /* dummy for result of cost_agg */ QualCost qual_cost; node->aggstrategy = aggstrategy; node->numCols = numGroupCols; node->grpColIdx = grpColIdx; node->numGroups = numGroups; copy_plan_costsize(plan, lefttree); /* only care about copying size */ cost_agg(&agg_path, root, aggstrategy, numAggs, numGroupCols, numGroups, lefttree->startup_cost, lefttree->total_cost, lefttree->plan_rows); plan->startup_cost = agg_path.startup_cost; plan->total_cost = agg_path.total_cost; /* * We will produce a single output tuple if not grouping, and a tuple * per group otherwise. */ if (aggstrategy == AGG_PLAIN) plan->plan_rows = 1; else plan->plan_rows = numGroups; /* * We also need to account for the cost of evaluation of the qual (ie, * the HAVING clause) and the tlist. Note that cost_qual_eval doesn't * charge anything for Aggref nodes; this is okay since they are * really comparable to Vars. * * See notes in grouping_planner about why this routine and make_group * are the only ones in this file that worry about tlist eval cost. */ if (qual) { cost_qual_eval(&qual_cost, qual); plan->startup_cost += qual_cost.startup; plan->total_cost += qual_cost.startup; plan->total_cost += qual_cost.per_tuple * plan->plan_rows; } cost_qual_eval(&qual_cost, tlist); plan->startup_cost += qual_cost.startup; plan->total_cost += qual_cost.startup; plan->total_cost += qual_cost.per_tuple * plan->plan_rows; plan->qual = qual; plan->targetlist = tlist; plan->lefttree = lefttree; plan->righttree = (Plan *) NULL; return node;}Group *make_group(Query *root, List *tlist, int numGroupCols, AttrNumber *grpColIdx, double numGroups, Plan *lefttree){ Group *node = makeNode(Group); Plan *plan = &node->plan; Path group_path; /* dummy for result of cost_group */ QualCost qual_cost; node->numCols = numGroupCols; node->grpColIdx = grpColIdx; copy_plan_costsize(plan, lefttree); /* only care about copying size */ cost_group(&group_path, root, numGroupCols, numGroups, lefttree->startup_cost, lefttree->total_cost, lefttree->plan_rows); plan->startup_cost = group_path.startup_cost; plan->total_cost = group_path.total_cost; /* One output tuple per estimated result group */ plan->plan_rows = numGroups; /* * We also need to account for the cost of evaluation of the tlist. * * XXX this double-counts the cost of evaluation of any expressions used * for grouping, since in reality those will have been evaluated at a * lower plan level and will only be copied by the Group node. Worth * fixing? * * See notes in grouping_planner about why this routine and make_agg are * the only ones in this file that worry about tlist eval cost. */ cost_qual_eval(&qual_cost, tlist); plan->startup_cost += qual_cost.startup; plan->total_cost += qual_cost.startup; plan->total_cost += qual_cost.per_tuple * plan->plan_rows; plan->qual = NIL; plan->targetlist = tlist; plan->lefttree = lefttree; plan->righttree = (Plan *) NULL; return node;}/* * distinctList is a list of SortClauses, identifying the targetlist items * that should be considered by the Unique filter. */Unique *make_unique(List *tlist, Plan *lefttree, List *distinctList){ Unique *node = makeNode(Unique); Plan *plan = &node->plan; int numCols = length(distinctList); int keyno = 0; AttrNumber *uniqColIdx; List *slitem; copy_plan_costsize(plan, lefttree); /* * Charge one cpu_operator_cost per comparison per input tuple. We * assume all columns get compared at most of the tuples. (XXX * probably this is an overestimate.) */ plan->total_cost += cpu_operator_cost * plan->plan_rows * numCols; /* * plan->plan_rows is left as a copy of the input subplan's plan_rows; * ie, we assume the filter removes nothing. The caller must alter * this if he has a better idea. */ plan->targetlist = tlist; plan->qual = NIL; plan->lefttree = lefttree; plan->righttree = NULL; /* * convert SortClause list into array of attr indexes, as wanted by * exec */ Assert(numCols > 0); uniqColIdx = (AttrNumber *) palloc(sizeof(AttrNumber) * numCols); foreach(slitem, distinctList) { SortClause *sortcl = (SortClause *) lfirst(slitem); TargetEntry *tle = get_sortgroupclause_tle(sortcl, tlist); uniqColIdx[keyno++] = tle->resdom->resno; } node->numCols = numCols; node->uniqColIdx = uniqColIdx; return node;}/* * distinctList is a list of SortClauses, identifying the targetlist items * that should be considered by the SetOp filter. */SetOp *make_setop(SetOpCmd cmd, List *tlist, Plan *lefttree, List *distinctList, AttrNumber flagColIdx){ SetOp *node = makeNode(SetOp); Plan *plan = &node->plan; int numCols = length(distinctList); int keyno = 0; AttrNumber *dupColIdx; List *slitem; copy_plan_costsize(plan, lefttree); /* * Charge one cpu_operator_cost per comparison per input tuple. We * assume all columns get compared at most of the tuples. */ plan->total_cost += cpu_operator_cost * plan->plan_rows * numCols; /* * We make the unsupported assumption that there will be 10% as many * tuples out as in. Any way to do better? */ plan->plan_rows *= 0.1; if (plan->plan_rows < 1) plan->plan_rows = 1; plan->targetlist = tlist; plan->qual = NIL; plan->lefttree = lefttree; plan->righttree = NULL; /* * convert SortClause list into array of attr indexes, as wanted by * exec */ Assert(numCols > 0); dupColIdx = (AttrNumber *) palloc(sizeof(AttrNumber) * numCols); foreach(slitem, distinctList) { SortClause *sortcl = (SortClause *) lfirst(slitem); TargetEntry *tle = get_sortgroupclause_tle(sortcl, tlist); dupColIdx[keyno++] = tle->resdom->resno; } node->cmd = cmd; node->numCols = numCols; node->dupColIdx = dupColIdx; node->flagColIdx = flagColIdx; return node;}Limit *make_limit(List *tlist, Plan *lefttree, Node *limitOffset, Node *limitCount){ Limit *node = makeNode(Limit); Plan *plan = &node->plan; copy_plan_costsize(plan, lefttree); /* * If offset/count are constants, adjust the output rows count and * costs accordingly. This is only a cosmetic issue if we are at top * level, but if we are building a subquery then it's important to * report correct info to the outer planner. */ if (limitOffset && IsA(limitOffset, Const)) { Const *limito = (Const *) limitOffset; int32 offset = DatumGetInt32(limito->con
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -