|
41 | 41 | #include "executor/nodeWindowAgg.h" |
42 | 42 | #include "miscadmin.h" |
43 | 43 | #include "nodes/nodeFuncs.h" |
| 44 | +#include "optimizer/clauses.h" |
44 | 45 | #include "optimizer/optimizer.h" |
45 | 46 | #include "parser/parse_agg.h" |
46 | 47 | #include "parser/parse_coerce.h" |
@@ -2803,16 +2804,24 @@ initialize_peragg(WindowAggState *winstate, WindowFunc *wfunc, |
2803 | 2804 | * aggregate's arguments (and FILTER clause if any) contain any calls to |
2804 | 2805 | * volatile functions. Otherwise, the difference between restarting and |
2805 | 2806 | * not restarting the aggregation would be user-visible. |
| 2807 | + * |
| 2808 | + * We also don't risk using moving aggregates when there are subplans in |
| 2809 | + * the arguments or FILTER clause. This is partly because |
| 2810 | + * contain_volatile_functions() doesn't look inside subplans; but there |
| 2811 | + * are other reasons why a subplan's output might be volatile. For |
| 2812 | + * example, syncscan mode can render the results nonrepeatable. |
2806 | 2813 | */ |
2807 | 2814 | if (!OidIsValid(aggform->aggminvtransfn)) |
2808 | 2815 | use_ma_code = false; /* sine qua non */ |
2809 | 2816 | else if (aggform->aggmfinalmodify == AGGMODIFY_READ_ONLY && |
2810 | | - aggform->aggfinalmodify != AGGMODIFY_READ_ONLY) |
| 2817 | + aggform->aggfinalmodify != AGGMODIFY_READ_ONLY) |
2811 | 2818 | use_ma_code = true; /* decision forced by safety */ |
2812 | 2819 | else if (winstate->frameOptions & FRAMEOPTION_START_UNBOUNDED_PRECEDING) |
2813 | 2820 | use_ma_code = false; /* non-moving frame head */ |
2814 | 2821 | else if (contain_volatile_functions((Node *) wfunc)) |
2815 | 2822 | use_ma_code = false; /* avoid possible behavioral change */ |
| 2823 | + else if (contain_subplans((Node *) wfunc)) |
| 2824 | + use_ma_code = false; /* subplans might contain volatile functions */ |
2816 | 2825 | else |
2817 | 2826 | use_ma_code = true; /* yes, let's use it */ |
2818 | 2827 | if (use_ma_code) |
|
0 commit comments