88 *
99 *
1010 * IDENTIFICATION
11- * $PostgreSQL: pgsql/src/backend/optimizer/plan/planner.c,v 1.252 2009/03/24 21:12:56 tgl Exp $
11+ * $PostgreSQL: pgsql/src/backend/optimizer/plan/planner.c,v 1.253 2009/03/30 17:30:44 tgl Exp $
1212 *
1313 *-------------------------------------------------------------------------
1414 */
@@ -83,6 +83,8 @@ static void locate_grouping_columns(PlannerInfo *root,
8383AttrNumber * groupColIdx );
8484static List * postprocess_setop_tlist (List * new_tlist ,List * orig_tlist );
8585static List * select_active_windows (PlannerInfo * root ,WindowFuncLists * wflists );
86+ static List * add_volatile_sort_exprs (List * window_tlist ,List * tlist ,
87+ List * activeWindows );
8688static List * make_pathkeys_for_window (PlannerInfo * root ,WindowClause * wc ,
8789List * tlist ,bool canonicalize );
8890static void get_column_info_for_window (PlannerInfo * root ,WindowClause * wc ,
@@ -1305,7 +1307,10 @@ grouping_planner(PlannerInfo *root, double tuple_fraction)
13051307 * (In some cases we wouldn't need to propagate all of these
13061308 * all the way to the top, since they might only be needed as
13071309 * inputs to WindowFuncs. It's probably not worth trying to
1308- * optimize that though.) As we climb up the stack, we add
1310+ * optimize that though.) We also need any volatile sort
1311+ * expressions, because make_sort_from_pathkeys won't add those
1312+ * on its own, and anyway we want them evaluated only once at
1313+ * the bottom of the stack. As we climb up the stack, we add
13091314 * outputs for the WindowFuncs computed at each level. Also,
13101315 * each input tlist has to present all the columns needed to
13111316 * sort the data for the next WindowAgg step. That's handled
@@ -1317,6 +1322,8 @@ grouping_planner(PlannerInfo *root, double tuple_fraction)
13171322if (parse -> hasAggs )
13181323window_tlist = add_to_flat_tlist (window_tlist ,
13191324pull_agg_clause ((Node * )tlist ));
1325+ window_tlist = add_volatile_sort_exprs (window_tlist ,tlist ,
1326+ activeWindows );
13201327result_plan -> targetlist = (List * )copyObject (window_tlist );
13211328
13221329foreach (l ,activeWindows )
@@ -2429,6 +2436,68 @@ select_active_windows(PlannerInfo *root, WindowFuncLists *wflists)
24292436return result ;
24302437}
24312438
2439+ /*
2440+ * add_volatile_sort_exprs
2441+ *Identify any volatile sort/group expressions used by the active
2442+ *windows, and add them to window_tlist if not already present.
2443+ *Return the modified window_tlist.
2444+ */
2445+ static List *
2446+ add_volatile_sort_exprs (List * window_tlist ,List * tlist ,List * activeWindows )
2447+ {
2448+ Bitmapset * sgrefs = NULL ;
2449+ ListCell * lc ;
2450+
2451+ /* First, collect the sortgrouprefs of the windows into a bitmapset */
2452+ foreach (lc ,activeWindows )
2453+ {
2454+ WindowClause * wc = (WindowClause * )lfirst (lc );
2455+ ListCell * lc2 ;
2456+
2457+ foreach (lc2 ,wc -> partitionClause )
2458+ {
2459+ SortGroupClause * sortcl = (SortGroupClause * )lfirst (lc2 );
2460+
2461+ sgrefs = bms_add_member (sgrefs ,sortcl -> tleSortGroupRef );
2462+ }
2463+ foreach (lc2 ,wc -> orderClause )
2464+ {
2465+ SortGroupClause * sortcl = (SortGroupClause * )lfirst (lc2 );
2466+
2467+ sgrefs = bms_add_member (sgrefs ,sortcl -> tleSortGroupRef );
2468+ }
2469+ }
2470+
2471+ /*
2472+ * Now scan the original tlist to find the referenced expressions.
2473+ * Any that are volatile must be added to window_tlist.
2474+ *
2475+ * Note: we know that the input window_tlist contains no items marked
2476+ * with ressortgrouprefs, so we don't have to worry about collisions
2477+ * of the reference numbers.
2478+ */
2479+ foreach (lc ,tlist )
2480+ {
2481+ TargetEntry * tle = (TargetEntry * )lfirst (lc );
2482+
2483+ if (tle -> ressortgroupref != 0 &&
2484+ bms_is_member (tle -> ressortgroupref ,sgrefs )&&
2485+ contain_volatile_functions ((Node * )tle -> expr ))
2486+ {
2487+ TargetEntry * newtle ;
2488+
2489+ newtle = makeTargetEntry (tle -> expr ,
2490+ list_length (window_tlist )+ 1 ,
2491+ NULL ,
2492+ false);
2493+ newtle -> ressortgroupref = tle -> ressortgroupref ;
2494+ window_tlist = lappend (window_tlist ,newtle );
2495+ }
2496+ }
2497+
2498+ return window_tlist ;
2499+ }
2500+
24322501/*
24332502 * make_pathkeys_for_window
24342503 *Create a pathkeys list describing the required input ordering