|
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