Commit 51c0f63e authored by Tom Lane's avatar Tom Lane

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.
parent 2f1f4439
This diff is collapsed.
......@@ -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);
/* 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
......
......@@ -623,6 +623,66 @@ make_tlist_from_pathtarget(PathTarget *target)
return tlist;
}
/*
* 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
......
......@@ -56,6 +56,9 @@ extern bool grouping_is_hashable(List *groupClause);
extern PathTarget *make_pathtarget_from_tlist(List *tlist);
extern List *make_tlist_from_pathtarget(PathTarget *target);
extern PathTarget *copy_pathtarget(PathTarget *src);
extern void add_column_to_pathtarget(PathTarget *target,
Expr *expr, Index sortgroupref);
extern void apply_pathtarget_labeling_to_tlist(List *tlist, PathTarget *target);
/* Convenience macro to get a PathTarget with valid cost/width fields */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment