aboutsummaryrefslogtreecommitdiff
path: root/src/backend/optimizer/util/tlist.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/optimizer/util/tlist.c')
-rw-r--r--src/backend/optimizer/util/tlist.c60
1 files changed, 60 insertions, 0 deletions
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
*