summaryrefslogtreecommitdiff
path: root/src/backend/optimizer/plan/planner.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/optimizer/plan/planner.c')
-rw-r--r--src/backend/optimizer/plan/planner.c201
1 files changed, 108 insertions, 93 deletions
diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c
index db91b8277d9..df274fe7830 100644
--- a/src/backend/optimizer/plan/planner.c
+++ b/src/backend/optimizer/plan/planner.c
@@ -59,7 +59,14 @@ planner_hook_type planner_hook = NULL;
#define EXPRKIND_APPINFO 7
#define EXPRKIND_PHV 8
+/* Passthrough data for standard_qp_callback */
+typedef struct
+{
+ List *tlist; /* preprocessed query targetlist */
+ List *activeWindows; /* active windows, if any */
+} standard_qp_extra;
+/* Local functions */
static Node *preprocess_expression(PlannerInfo *root, Node *expr, int kind);
static void preprocess_qual_conditions(PlannerInfo *root, Node *jtnode);
static Plan *inheritance_planner(PlannerInfo *root);
@@ -70,6 +77,7 @@ static double preprocess_limit(PlannerInfo *root,
int64 *offset_est, int64 *count_est);
static bool limit_needed(Query *parse);
static void preprocess_groupclause(PlannerInfo *root);
+static void standard_qp_callback(PlannerInfo *root, void *extra);
static bool choose_hashed_grouping(PlannerInfo *root,
double tuple_fraction, double limit_tuples,
double path_rows, int path_width,
@@ -94,7 +102,7 @@ static List *select_active_windows(PlannerInfo *root, WindowFuncLists *wflists);
static List *make_windowInputTargetList(PlannerInfo *root,
List *tlist, List *activeWindows);
static List *make_pathkeys_for_window(PlannerInfo *root, WindowClause *wc,
- List *tlist, bool canonicalize);
+ List *tlist);
static void get_column_info_for_window(PlannerInfo *root, WindowClause *wc,
List *tlist,
int numSortCols, AttrNumber *sortColIdx,
@@ -1052,8 +1060,7 @@ grouping_planner(PlannerInfo *root, double tuple_fraction)
*/
current_pathkeys = make_pathkeys_for_sortclauses(root,
set_sortclauses,
- result_plan->targetlist,
- true);
+ result_plan->targetlist);
/*
* We should not need to call preprocess_targetlist, since we must be
@@ -1082,8 +1089,7 @@ grouping_planner(PlannerInfo *root, double tuple_fraction)
Assert(parse->distinctClause == NIL);
root->sort_pathkeys = make_pathkeys_for_sortclauses(root,
parse->sortClause,
- tlist,
- true);
+ tlist);
}
else
{
@@ -1092,6 +1098,7 @@ grouping_planner(PlannerInfo *root, double tuple_fraction)
double sub_limit_tuples;
AttrNumber *groupColIdx = NULL;
bool need_tlist_eval = true;
+ standard_qp_extra qp_extra;
Path *cheapest_path;
Path *sorted_path;
Path *best_path;
@@ -1168,82 +1175,6 @@ grouping_planner(PlannerInfo *root, double tuple_fraction)
}
/*
- * Calculate pathkeys that represent grouping/ordering requirements.
- * Stash them in PlannerInfo so that query_planner can canonicalize
- * them after EquivalenceClasses have been formed. The sortClause is
- * certainly sort-able, but GROUP BY and DISTINCT might not be, in
- * which case we just leave their pathkeys empty.
- */
- if (parse->groupClause &&
- grouping_is_sortable(parse->groupClause))
- root->group_pathkeys =
- make_pathkeys_for_sortclauses(root,
- parse->groupClause,
- tlist,
- false);
- else
- root->group_pathkeys = NIL;
-
- /* We consider only the first (bottom) window in pathkeys logic */
- if (activeWindows != NIL)
- {
- WindowClause *wc = (WindowClause *) linitial(activeWindows);
-
- root->window_pathkeys = make_pathkeys_for_window(root,
- wc,
- tlist,
- false);
- }
- else
- root->window_pathkeys = NIL;
-
- if (parse->distinctClause &&
- grouping_is_sortable(parse->distinctClause))
- root->distinct_pathkeys =
- make_pathkeys_for_sortclauses(root,
- parse->distinctClause,
- tlist,
- false);
- else
- root->distinct_pathkeys = NIL;
-
- root->sort_pathkeys =
- make_pathkeys_for_sortclauses(root,
- parse->sortClause,
- tlist,
- false);
-
- /*
- * Figure out whether we want a sorted result from query_planner.
- *
- * If we have a sortable GROUP BY clause, then we want a result sorted
- * properly for grouping. Otherwise, if we have window functions to
- * evaluate, we try to sort for the first window. Otherwise, if
- * there's a sortable DISTINCT clause that's more rigorous than the
- * ORDER BY clause, we try to produce output that's sufficiently well
- * sorted for the DISTINCT. Otherwise, if there is an ORDER BY
- * clause, we want to sort by the ORDER BY clause.
- *
- * Note: if we have both ORDER BY and GROUP BY, and ORDER BY is a
- * superset of GROUP BY, it would be tempting to request sort by ORDER
- * BY --- but that might just leave us failing to exploit an available
- * sort order at all. Needs more thought. The choice for DISTINCT
- * versus ORDER BY is much easier, since we know that the parser
- * ensured that one is a superset of the other.
- */
- if (root->group_pathkeys)
- root->query_pathkeys = root->group_pathkeys;
- else if (root->window_pathkeys)
- root->query_pathkeys = root->window_pathkeys;
- else if (list_length(root->distinct_pathkeys) >
- list_length(root->sort_pathkeys))
- root->query_pathkeys = root->distinct_pathkeys;
- else if (root->sort_pathkeys)
- root->query_pathkeys = root->sort_pathkeys;
- else
- root->query_pathkeys = NIL;
-
- /*
* Figure out whether there's a hard limit on the number of rows that
* query_planner's result subplan needs to return. Even if we know a
* hard limit overall, it doesn't apply if the query has any
@@ -1258,13 +1189,19 @@ grouping_planner(PlannerInfo *root, double tuple_fraction)
else
sub_limit_tuples = limit_tuples;
+ /* Set up data needed by standard_qp_callback */
+ qp_extra.tlist = tlist;
+ qp_extra.activeWindows = activeWindows;
+
/*
* Generate the best unsorted and presorted paths for this Query (but
- * note there may not be any presorted path). query_planner will also
- * estimate the number of groups in the query, and canonicalize all
- * the pathkeys.
+ * note there may not be any presorted path). We also generate (in
+ * standard_qp_callback) pathkey representations of the query's sort
+ * clause, distinct clause, etc. query_planner will also estimate the
+ * number of groups in the query.
*/
query_planner(root, sub_tlist, tuple_fraction, sub_limit_tuples,
+ standard_qp_callback, &qp_extra,
&cheapest_path, &sorted_path, &dNumGroups);
/*
@@ -1597,8 +1534,7 @@ grouping_planner(PlannerInfo *root, double tuple_fraction)
window_pathkeys = make_pathkeys_for_window(root,
wc,
- tlist,
- true);
+ tlist);
/*
* This is a bit tricky: we build a sort node even if we don't
@@ -2440,6 +2376,88 @@ preprocess_groupclause(PlannerInfo *root)
}
/*
+ * Compute query_pathkeys and other pathkeys during plan generation
+ */
+static void
+standard_qp_callback(PlannerInfo *root, void *extra)
+{
+ Query *parse = root->parse;
+ standard_qp_extra *qp_extra = (standard_qp_extra *) extra;
+ List *tlist = qp_extra->tlist;
+ List *activeWindows = qp_extra->activeWindows;
+
+ /*
+ * Calculate pathkeys that represent grouping/ordering requirements. The
+ * sortClause is certainly sort-able, but GROUP BY and DISTINCT might not
+ * be, in which case we just leave their pathkeys empty.
+ */
+ if (parse->groupClause &&
+ grouping_is_sortable(parse->groupClause))
+ root->group_pathkeys =
+ make_pathkeys_for_sortclauses(root,
+ parse->groupClause,
+ tlist);
+ else
+ root->group_pathkeys = NIL;
+
+ /* We consider only the first (bottom) window in pathkeys logic */
+ if (activeWindows != NIL)
+ {
+ WindowClause *wc = (WindowClause *) linitial(activeWindows);
+
+ root->window_pathkeys = make_pathkeys_for_window(root,
+ wc,
+ tlist);
+ }
+ else
+ root->window_pathkeys = NIL;
+
+ if (parse->distinctClause &&
+ grouping_is_sortable(parse->distinctClause))
+ root->distinct_pathkeys =
+ make_pathkeys_for_sortclauses(root,
+ parse->distinctClause,
+ tlist);
+ else
+ root->distinct_pathkeys = NIL;
+
+ root->sort_pathkeys =
+ make_pathkeys_for_sortclauses(root,
+ parse->sortClause,
+ tlist);
+
+ /*
+ * Figure out whether we want a sorted result from query_planner.
+ *
+ * If we have a sortable GROUP BY clause, then we want a result sorted
+ * properly for grouping. Otherwise, if we have window functions to
+ * evaluate, we try to sort for the first window. Otherwise, if there's a
+ * sortable DISTINCT clause that's more rigorous than the ORDER BY clause,
+ * we try to produce output that's sufficiently well sorted for the
+ * DISTINCT. Otherwise, if there is an ORDER BY clause, we want to sort
+ * by the ORDER BY clause.
+ *
+ * Note: if we have both ORDER BY and GROUP BY, and ORDER BY is a superset
+ * of GROUP BY, it would be tempting to request sort by ORDER BY --- but
+ * that might just leave us failing to exploit an available sort order at
+ * all. Needs more thought. The choice for DISTINCT versus ORDER BY is
+ * much easier, since we know that the parser ensured that one is a
+ * superset of the other.
+ */
+ if (root->group_pathkeys)
+ root->query_pathkeys = root->group_pathkeys;
+ else if (root->window_pathkeys)
+ root->query_pathkeys = root->window_pathkeys;
+ else if (list_length(root->distinct_pathkeys) >
+ list_length(root->sort_pathkeys))
+ root->query_pathkeys = root->distinct_pathkeys;
+ else if (root->sort_pathkeys)
+ root->query_pathkeys = root->sort_pathkeys;
+ else
+ root->query_pathkeys = NIL;
+}
+
+/*
* choose_hashed_grouping - should we use hashed grouping?
*
* Returns TRUE to select hashing, FALSE to select sorting.
@@ -3235,7 +3253,7 @@ make_windowInputTargetList(PlannerInfo *root,
*/
static List *
make_pathkeys_for_window(PlannerInfo *root, WindowClause *wc,
- List *tlist, bool canonicalize)
+ List *tlist)
{
List *window_pathkeys;
List *window_sortclauses;
@@ -3257,8 +3275,7 @@ make_pathkeys_for_window(PlannerInfo *root, WindowClause *wc,
list_copy(wc->orderClause));
window_pathkeys = make_pathkeys_for_sortclauses(root,
window_sortclauses,
- tlist,
- canonicalize);
+ tlist);
list_free(window_sortclauses);
return window_pathkeys;
}
@@ -3336,8 +3353,7 @@ get_column_info_for_window(PlannerInfo *root, WindowClause *wc, List *tlist,
sortclauses = lappend(sortclauses, sgc);
new_pathkeys = make_pathkeys_for_sortclauses(root,
sortclauses,
- tlist,
- true);
+ tlist);
if (list_length(new_pathkeys) > list_length(pathkeys))
{
/* this sort clause is actually significant */
@@ -3355,8 +3371,7 @@ get_column_info_for_window(PlannerInfo *root, WindowClause *wc, List *tlist,
sortclauses = lappend(sortclauses, sgc);
new_pathkeys = make_pathkeys_for_sortclauses(root,
sortclauses,
- tlist,
- true);
+ tlist);
if (list_length(new_pathkeys) > list_length(pathkeys))
{
/* this sort clause is actually significant */