aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorNoah Misch <noah@leadboat.com>2013-07-16 20:14:37 -0400
committerNoah Misch <noah@leadboat.com>2013-07-16 20:14:37 -0400
commit7a8e9f298e7b8158296e1ea72ca8987323c10edf (patch)
treef71804cf8d203d25a07cc86354c9cce2cc5e336b /src
parent4a87f308b33457670f9ab4bc622678e5d285b9c2 (diff)
downloadpostgresql-7a8e9f298e7b8158296e1ea72ca8987323c10edf.tar.gz
postgresql-7a8e9f298e7b8158296e1ea72ca8987323c10edf.zip
Comment on why planagg.c punts "MIN(x ORDER BY y)".
Diffstat (limited to 'src')
-rw-r--r--src/backend/optimizer/plan/planagg.c18
1 files changed, 16 insertions, 2 deletions
diff --git a/src/backend/optimizer/plan/planagg.c b/src/backend/optimizer/plan/planagg.c
index 090ae0b494c..bc13f2cce44 100644
--- a/src/backend/optimizer/plan/planagg.c
+++ b/src/backend/optimizer/plan/planagg.c
@@ -314,15 +314,29 @@ find_minmax_aggs_walker(Node *node, List **context)
ListCell *l;
Assert(aggref->agglevelsup == 0);
- if (list_length(aggref->args) != 1 || aggref->aggorder != NIL)
+ if (list_length(aggref->args) != 1)
return true; /* it couldn't be MIN/MAX */
+ /*
+ * ORDER BY is usually irrelevant for MIN/MAX, but it can change the
+ * outcome if the aggsortop's operator class recognizes non-identical
+ * values as equal. For example, 4.0 and 4.00 are equal according to
+ * numeric_ops, yet distinguishable. If MIN() receives more than one
+ * value equal to 4.0 and no value less than 4.0, it is unspecified
+ * which of those equal values MIN() returns. An ORDER BY expression
+ * that differs for each of those equal values of the argument
+ * expression makes the result predictable once again. This is a
+ * niche requirement, and we do not implement it with subquery paths.
+ */
+ if (aggref->aggorder != NIL)
+ return true;
/* note: we do not care if DISTINCT is mentioned ... */
- curTarget = (TargetEntry *) linitial(aggref->args);
aggsortop = fetch_agg_sort_op(aggref->aggfnoid);
if (!OidIsValid(aggsortop))
return true; /* not a MIN/MAX aggregate */
+ curTarget = (TargetEntry *) linitial(aggref->args);
+
if (contain_mutable_functions((Node *) curTarget->expr))
return true; /* not potentially indexable */