@@ -314,15 +314,29 @@ find_minmax_aggs_walker(Node *node, List **context)
314
314
ListCell * l ;
315
315
316
316
Assert (aggref -> agglevelsup == 0 );
317
- if (list_length (aggref -> args ) != 1 || aggref -> aggorder != NIL )
317
+ if (list_length (aggref -> args ) != 1 )
318
318
return true; /* it couldn't be MIN/MAX */
319
+ /*
320
+ * ORDER BY is usually irrelevant for MIN/MAX, but it can change the
321
+ * outcome if the aggsortop's operator class recognizes non-identical
322
+ * values as equal. For example, 4.0 and 4.00 are equal according to
323
+ * numeric_ops, yet distinguishable. If MIN() receives more than one
324
+ * value equal to 4.0 and no value less than 4.0, it is unspecified
325
+ * which of those equal values MIN() returns. An ORDER BY expression
326
+ * that differs for each of those equal values of the argument
327
+ * expression makes the result predictable once again. This is a
328
+ * niche requirement, and we do not implement it with subquery paths.
329
+ */
330
+ if (aggref -> aggorder != NIL )
331
+ return true;
319
332
/* note: we do not care if DISTINCT is mentioned ... */
320
- curTarget = (TargetEntry * ) linitial (aggref -> args );
321
333
322
334
aggsortop = fetch_agg_sort_op (aggref -> aggfnoid );
323
335
if (!OidIsValid (aggsortop ))
324
336
return true; /* not a MIN/MAX aggregate */
325
337
338
+ curTarget = (TargetEntry * ) linitial (aggref -> args );
339
+
326
340
if (contain_mutable_functions ((Node * ) curTarget -> expr ))
327
341
return true; /* not potentially indexable */
328
342
0 commit comments