/*
* build_base_rel_tlists
* Add targetlist entries for each var needed in the query's final tlist
- * to the appropriate base relations.
+ * (and HAVING clause, if any) to the appropriate base relations.
*
* We mark such vars as needed by "relation 0" to ensure that they will
* propagate up through all join plan steps.
add_vars_to_targetlist(root, tlist_vars, bms_make_singleton(0), true);
list_free(tlist_vars);
}
+
+ /*
+ * If there's a HAVING clause, we'll need the Vars it uses, too.
+ */
+ if (root->parse->havingQual)
+ {
+ List *having_vars = pull_var_clause(root->parse->havingQual,
+ PVC_RECURSE_AGGREGATES,
+ PVC_INCLUDE_PLACEHOLDERS);
+
+ if (having_vars != NIL)
+ {
+ add_vars_to_targetlist(root, having_vars,
+ bms_make_singleton(0), true);
+ list_free(having_vars);
+ }
+ }
}
/*
else
{
/* No set operations, do regular planning */
- List *sub_tlist;
- AttrNumber *groupColIdx = NULL;
- bool need_tlist_eval = true;
long numGroups = 0;
AggClauseCosts agg_costs;
int numGroupCols;
parse->hasWindowFuncs = false;
}
- /*
- * Generate appropriate target list for subplan; may be different from
- * tlist if grouping or aggregation is needed.
- */
- sub_tlist = make_subplanTargetList(root, tlist,
- &groupColIdx, &need_tlist_eval);
-
/*
* Do aggregate preprocessing, if the query has any aggs.
*
* standard_qp_callback) pathkey representations of the query's sort
* clause, distinct clause, etc.
*/
- final_rel = query_planner(root, sub_tlist,
+ final_rel = query_planner(root, tlist,
standard_qp_callback, &qp_extra);
/*
* Normal case --- create a plan according to query_planner's
* results.
*/
+ List *sub_tlist;
+ AttrNumber *groupColIdx = NULL;
+ bool need_tlist_eval = true;
bool need_sort_for_grouping = false;
result_plan = create_plan(root, best_path);
/* Detect if we'll need an explicit sort for grouping */
if (parse->groupClause && !use_hashed_grouping &&
!pathkeys_contained_in(root->group_pathkeys, current_pathkeys))
- {
need_sort_for_grouping = true;
- /*
- * Always override create_plan's tlist, so that we don't sort
- * useless data from a "physical" tlist.
- */
- need_tlist_eval = true;
- }
+ /*
+ * Generate appropriate target list for scan/join subplan; may be
+ * different from tlist if grouping or aggregation is needed.
+ */
+ sub_tlist = make_subplanTargetList(root, tlist,
+ &groupColIdx,
+ &need_tlist_eval);
/*
* create_plan returns a plan with just a "flat" tlist of required
* Vars. Usually we need to insert the sub_tlist as the tlist of
* the top plan node. However, we can skip that if we determined
* that whatever create_plan chose to return will be good enough.
+ *
+ * If we need_sort_for_grouping, always override create_plan's
+ * tlist, so that we don't sort useless data from a "physical"
+ * tlist.
*/
- if (need_tlist_eval)
+ if (need_tlist_eval || need_sort_for_grouping)
{
/*
* If the top-level plan node is one that cannot do expression