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