@@ -142,7 +142,8 @@ static void subquery_push_qual(Query *subquery,
142
142
RangeTblEntry * rte , Index rti , Node * qual );
143
143
static void recurse_push_qual (Node * setOp , Query * topquery ,
144
144
RangeTblEntry * rte , Index rti , Node * qual );
145
- static void remove_unused_subquery_outputs (Query * subquery , RelOptInfo * rel );
145
+ static void remove_unused_subquery_outputs (Query * subquery , RelOptInfo * rel ,
146
+ Bitmapset * extra_used_attrs );
146
147
147
148
148
149
/*
@@ -2177,14 +2178,16 @@ has_multiple_baserels(PlannerInfo *root)
2177
2178
* the run condition will handle all of the required filtering.
2178
2179
*
2179
2180
* Returns true if 'opexpr' was found to be useful and was added to the
2180
- * WindowClauses runCondition. We also set *keep_original accordingly.
2181
+ * WindowClauses runCondition. We also set *keep_original accordingly and add
2182
+ * 'attno' to *run_cond_attrs offset by FirstLowInvalidHeapAttributeNumber.
2181
2183
* If the 'opexpr' cannot be used then we set *keep_original to true and
2182
2184
* return false.
2183
2185
*/
2184
2186
static bool
2185
2187
find_window_run_conditions (Query * subquery , RangeTblEntry * rte , Index rti ,
2186
2188
AttrNumber attno , WindowFunc * wfunc , OpExpr * opexpr ,
2187
- bool wfunc_left , bool * keep_original )
2189
+ bool wfunc_left , bool * keep_original ,
2190
+ Bitmapset * * run_cond_attrs )
2188
2191
{
2189
2192
Oid prosupport ;
2190
2193
Expr * otherexpr ;
@@ -2356,6 +2359,9 @@ find_window_run_conditions(Query *subquery, RangeTblEntry *rte, Index rti,
2356
2359
2357
2360
wclause -> runCondition = lappend (wclause -> runCondition , newexpr );
2358
2361
2362
+ /* record that this attno was used in a run condition */
2363
+ * run_cond_attrs = bms_add_member (* run_cond_attrs ,
2364
+ attno - FirstLowInvalidHeapAttributeNumber );
2359
2365
return true;
2360
2366
}
2361
2367
@@ -2369,13 +2375,17 @@ find_window_run_conditions(Query *subquery, RangeTblEntry *rte, Index rti,
2369
2375
* WindowClause as a 'runCondition' qual. These, when present, allow
2370
2376
* some unnecessary work to be skipped during execution.
2371
2377
*
2378
+ * 'run_cond_attrs' will be populated with all targetlist resnos of subquery
2379
+ * targets (offset by FirstLowInvalidHeapAttributeNumber) that we pushed
2380
+ * window quals for.
2381
+ *
2372
2382
* Returns true if the caller still must keep the original qual or false if
2373
2383
* the caller can safely ignore the original qual because the WindowAgg node
2374
2384
* will use the runCondition to stop returning tuples.
2375
2385
*/
2376
2386
static bool
2377
2387
check_and_push_window_quals (Query * subquery , RangeTblEntry * rte , Index rti ,
2378
- Node * clause )
2388
+ Node * clause , Bitmapset * * run_cond_attrs )
2379
2389
{
2380
2390
OpExpr * opexpr = (OpExpr * ) clause ;
2381
2391
bool keep_original = true;
@@ -2403,7 +2413,8 @@ check_and_push_window_quals(Query *subquery, RangeTblEntry *rte, Index rti,
2403
2413
WindowFunc * wfunc = (WindowFunc * ) tle -> expr ;
2404
2414
2405
2415
if (find_window_run_conditions (subquery , rte , rti , tle -> resno , wfunc ,
2406
- opexpr , true, & keep_original ))
2416
+ opexpr , true, & keep_original ,
2417
+ run_cond_attrs ))
2407
2418
return keep_original ;
2408
2419
}
2409
2420
@@ -2415,7 +2426,8 @@ check_and_push_window_quals(Query *subquery, RangeTblEntry *rte, Index rti,
2415
2426
WindowFunc * wfunc = (WindowFunc * ) tle -> expr ;
2416
2427
2417
2428
if (find_window_run_conditions (subquery , rte , rti , tle -> resno , wfunc ,
2418
- opexpr , false, & keep_original ))
2429
+ opexpr , false, & keep_original ,
2430
+ run_cond_attrs ))
2419
2431
return keep_original ;
2420
2432
}
2421
2433
@@ -2444,6 +2456,7 @@ set_subquery_pathlist(PlannerInfo *root, RelOptInfo *rel,
2444
2456
pushdown_safety_info safetyInfo ;
2445
2457
double tuple_fraction ;
2446
2458
RelOptInfo * sub_final_rel ;
2459
+ Bitmapset * run_cond_attrs = NULL ;
2447
2460
ListCell * lc ;
2448
2461
2449
2462
/*
@@ -2526,7 +2539,8 @@ set_subquery_pathlist(PlannerInfo *root, RelOptInfo *rel,
2526
2539
* it might be useful to use for the WindowAgg's runCondition.
2527
2540
*/
2528
2541
if (!subquery -> hasWindowFuncs ||
2529
- check_and_push_window_quals (subquery , rte , rti , clause ))
2542
+ check_and_push_window_quals (subquery , rte , rti , clause ,
2543
+ & run_cond_attrs ))
2530
2544
{
2531
2545
/*
2532
2546
* subquery has no window funcs or the clause is not a
@@ -2545,9 +2559,11 @@ set_subquery_pathlist(PlannerInfo *root, RelOptInfo *rel,
2545
2559
2546
2560
/*
2547
2561
* The upper query might not use all the subquery's output columns; if
2548
- * not, we can simplify.
2562
+ * not, we can simplify. Pass the attributes that were pushed down into
2563
+ * WindowAgg run conditions to ensure we don't accidentally think those
2564
+ * are unused.
2549
2565
*/
2550
- remove_unused_subquery_outputs (subquery , rel );
2566
+ remove_unused_subquery_outputs (subquery , rel , run_cond_attrs );
2551
2567
2552
2568
/*
2553
2569
* We can safely pass the outer tuple_fraction down to the subquery if the
@@ -3945,16 +3961,28 @@ recurse_push_qual(Node *setOp, Query *topquery,
3945
3961
* compute expressions, but because deletion of output columns might allow
3946
3962
* optimizations such as join removal to occur within the subquery.
3947
3963
*
3964
+ * extra_used_attrs can be passed as non-NULL to mark any columns (offset by
3965
+ * FirstLowInvalidHeapAttributeNumber) that we should not remove. This
3966
+ * parameter is modifed by the function, so callers must make a copy if they
3967
+ * need to use the passed in Bitmapset after calling this function.
3968
+ *
3948
3969
* To avoid affecting column numbering in the targetlist, we don't physically
3949
3970
* remove unused tlist entries, but rather replace their expressions with NULL
3950
3971
* constants. This is implemented by modifying subquery->targetList.
3951
3972
*/
3952
3973
static void
3953
- remove_unused_subquery_outputs (Query * subquery , RelOptInfo * rel )
3974
+ remove_unused_subquery_outputs (Query * subquery , RelOptInfo * rel ,
3975
+ Bitmapset * extra_used_attrs )
3954
3976
{
3955
- Bitmapset * attrs_used = NULL ;
3977
+ Bitmapset * attrs_used ;
3956
3978
ListCell * lc ;
3957
3979
3980
+ /*
3981
+ * Just point directly to extra_used_attrs. No need to bms_copy as none of
3982
+ * the current callers use the Bitmapset after calling this function.
3983
+ */
3984
+ attrs_used = extra_used_attrs ;
3985
+
3958
3986
/*
3959
3987
* Do nothing if subquery has UNION/INTERSECT/EXCEPT: in principle we
3960
3988
* could update all the child SELECTs' tlists, but it seems not worth the
0 commit comments