diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2016-03-09 01:12:16 -0500 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2016-03-09 01:12:16 -0500 |
commit | 51c0f63e4d76a86b44e87876a6addcfffb01ec28 (patch) | |
tree | 374c1c1c14b31d20b65785c6264a9fad6c1a0c86 /src/backend/optimizer/util | |
parent | 2f1f4439306d2793492e49366d5911e48aa2c4b1 (diff) |
Improve handling of pathtargets in planner.c.
Refactor so that the internal APIs in planner.c deal in PathTargets not
targetlists, and establish a more regular structure for deriving the
targets needed for successive steps.
There is more that could be done here; calculating the eval costs of each
successive target independently is both inefficient and wrong in detail,
since we won't actually recompute values available from the input node's
tlist. But it's no worse than what happened before the pathification
rewrite. In any case this seems like a good starting point for considering
how to handle Konstantin Knizhnik's function-evaluation-postponement patch.
Diffstat (limited to 'src/backend/optimizer/util')
-rw-r--r-- | src/backend/optimizer/util/clauses.c | 10 | ||||
-rw-r--r-- | src/backend/optimizer/util/tlist.c | 60 |
2 files changed, 67 insertions, 3 deletions
diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c index 6ac25dc6638..b692e18e3d4 100644 --- a/src/backend/optimizer/util/clauses.c +++ b/src/backend/optimizer/util/clauses.c @@ -672,9 +672,13 @@ find_window_functions_walker(Node *node, WindowFuncLists *lists) if (wfunc->winref > lists->maxWinRef) elog(ERROR, "WindowFunc contains out-of-range winref %u", wfunc->winref); - lists->windowFuncs[wfunc->winref] = - lappend(lists->windowFuncs[wfunc->winref], wfunc); - lists->numWindowFuncs++; + /* eliminate duplicates, so that we avoid repeated computation */ + if (!list_member(lists->windowFuncs[wfunc->winref], wfunc)) + { + lists->windowFuncs[wfunc->winref] = + lappend(lists->windowFuncs[wfunc->winref], wfunc); + lists->numWindowFuncs++; + } /* * We assume that the parser checked that there are no window diff --git a/src/backend/optimizer/util/tlist.c b/src/backend/optimizer/util/tlist.c index c51642fde5b..ccea3bf9d27 100644 --- a/src/backend/optimizer/util/tlist.c +++ b/src/backend/optimizer/util/tlist.c @@ -624,6 +624,66 @@ make_tlist_from_pathtarget(PathTarget *target) } /* + * copy_pathtarget + * Copy a PathTarget. + * + * The new PathTarget has its own List cells, but shares the underlying + * target expression trees with the old one. We duplicate the List cells + * so that items can be added to one target without damaging the other. + */ +PathTarget * +copy_pathtarget(PathTarget *src) +{ + PathTarget *dst = (PathTarget *) palloc(sizeof(PathTarget)); + + /* Copy scalar fields */ + memcpy(dst, src, sizeof(PathTarget)); + /* Shallow-copy the expression list */ + dst->exprs = list_copy(src->exprs); + /* Duplicate sortgrouprefs if any (if not, the memcpy handled this) */ + if (src->sortgrouprefs) + { + Size nbytes = list_length(src->exprs) * sizeof(Index); + + dst->sortgrouprefs = (Index *) palloc(nbytes); + memcpy(dst->sortgrouprefs, src->sortgrouprefs, nbytes); + } + return dst; +} + +/* + * add_column_to_pathtarget + * Append a target column to the PathTarget. + * + * As with make_pathtarget_from_tlist, we leave it to the caller to update + * the cost and width fields. + */ +void +add_column_to_pathtarget(PathTarget *target, Expr *expr, Index sortgroupref) +{ + /* Updating the exprs list is easy ... */ + target->exprs = lappend(target->exprs, expr); + /* ... the sortgroupref data, a bit less so */ + if (target->sortgrouprefs) + { + int nexprs = list_length(target->exprs); + + /* This might look inefficient, but actually it's usually cheap */ + target->sortgrouprefs = (Index *) + repalloc(target->sortgrouprefs, nexprs * sizeof(Index)); + target->sortgrouprefs[nexprs - 1] = sortgroupref; + } + else if (sortgroupref) + { + /* Adding sortgroupref labeling to a previously unlabeled target */ + int nexprs = list_length(target->exprs); + + target->sortgrouprefs = (Index *) palloc0(nexprs * sizeof(Index)); + target->sortgrouprefs[nexprs - 1] = sortgroupref; + } +} + +/* * apply_pathtarget_labeling_to_tlist * Apply any sortgrouprefs in the PathTarget to matching tlist entries * |