|
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"
|
@@ -2662,16 +2663,24 @@ initialize_peragg(WindowAggState *winstate, WindowFunc *wfunc,
|
2662 | 2663 | * aggregate's arguments (and FILTER clause if any) contain any calls to
|
2663 | 2664 | * volatile functions. Otherwise, the difference between restarting and
|
2664 | 2665 | * not restarting the aggregation would be user-visible.
|
| 2666 | + * |
| 2667 | + * We also don't risk using moving aggregates when there are subplans in |
| 2668 | + * the arguments or FILTER clause. This is partly because |
| 2669 | + * contain_volatile_functions() doesn't look inside subplans; but there |
| 2670 | + * are other reasons why a subplan's output might be volatile. For |
| 2671 | + * example, syncscan mode can render the results nonrepeatable. |
2665 | 2672 | */
|
2666 | 2673 | if (!OidIsValid(aggform->aggminvtransfn))
|
2667 | 2674 | use_ma_code = false; /* sine qua non */
|
2668 | 2675 | else if (aggform->aggmfinalmodify == AGGMODIFY_READ_ONLY &&
|
2669 |
| - aggform->aggfinalmodify != AGGMODIFY_READ_ONLY) |
| 2676 | + aggform->aggfinalmodify != AGGMODIFY_READ_ONLY) |
2670 | 2677 | use_ma_code = true; /* decision forced by safety */
|
2671 | 2678 | else if (winstate->frameOptions & FRAMEOPTION_START_UNBOUNDED_PRECEDING)
|
2672 | 2679 | use_ma_code = false; /* non-moving frame head */
|
2673 | 2680 | else if (contain_volatile_functions((Node *) wfunc))
|
2674 | 2681 | use_ma_code = false; /* avoid possible behavioral change */
|
| 2682 | + else if (contain_subplans((Node *) wfunc)) |
| 2683 | + use_ma_code = false; /* subplans might contain volatile functions */ |
2675 | 2684 | else
|
2676 | 2685 | use_ma_code = true; /* yes, let's use it */
|
2677 | 2686 | if (use_ma_code)
|
|
0 commit comments