aboutsummaryrefslogtreecommitdiff
path: root/src/backend/parser/parse_clause.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2013-11-05 21:58:08 -0500
committerTom Lane <tgl@sss.pgh.pa.us>2013-11-05 21:58:08 -0500
commit920c8261d58c10de7e68d99c8dd21a9650928d59 (patch)
tree12770466f0d74f42e559b0bdcb5c72965711e65c /src/backend/parser/parse_clause.c
parentd4e6133c681f0038861e5cf8707302bd80917fa0 (diff)
downloadpostgresql-920c8261d58c10de7e68d99c8dd21a9650928d59.tar.gz
postgresql-920c8261d58c10de7e68d99c8dd21a9650928d59.zip
Improve the error message given for modifying a window with frame clause.
For rather inscrutable reasons, SQL:2008 disallows copying-and-modifying a window definition that has any explicit framing clause. The error message we gave for this only made sense if the referencing window definition itself contains an explicit framing clause, which it might well not. Moreover, in the context of an OVER clause it's not exactly obvious that "OVER (windowname)" implies copy-and-modify while "OVER windowname" does not. This has led to multiple complaints, eg bug #5199 from Iliya Krapchatov. Change to a hopefully more intelligible error message, and in the case where we have just "OVER (windowname)", add a HINT suggesting that omitting the parentheses will fix it. Also improve the related documentation. Back-patch to all supported branches.
Diffstat (limited to 'src/backend/parser/parse_clause.c')
-rw-r--r--src/backend/parser/parse_clause.c31
1 files changed, 26 insertions, 5 deletions
diff --git a/src/backend/parser/parse_clause.c b/src/backend/parser/parse_clause.c
index ea90e58f710..1f6306a7d35 100644
--- a/src/backend/parser/parse_clause.c
+++ b/src/backend/parser/parse_clause.c
@@ -1735,11 +1735,16 @@ transformWindowDefinitions(ParseState *pstate,
/*
* Per spec, a windowdef that references a previous one copies the
* previous partition clause (and mustn't specify its own). It can
- * specify its own ordering clause. but only if the previous one had
+ * specify its own ordering clause, but only if the previous one had
* none. It always specifies its own frame clause, and the previous
- * one must not have a frame clause. (Yeah, it's bizarre that each of
+ * one must not have a frame clause. Yeah, it's bizarre that each of
* these cases works differently, but SQL:2008 says so; see 7.11
- * <window clause> syntax rule 10 and general rule 1.)
+ * <window clause> syntax rule 10 and general rule 1. The frame
+ * clause rule is especially bizarre because it makes "OVER foo"
+ * different from "OVER (foo)", and requires the latter to throw an
+ * error if foo has a nondefault frame clause. Well, ours not to
+ * reason why, but we do go out of our way to throw a useful error
+ * message for such cases.
*/
if (refwc)
{
@@ -1778,11 +1783,27 @@ transformWindowDefinitions(ParseState *pstate,
wc->copiedOrder = false;
}
if (refwc && refwc->frameOptions != FRAMEOPTION_DEFAULTS)
+ {
+ /*
+ * Use this message if this is a WINDOW clause, or if it's an OVER
+ * clause that includes ORDER BY or framing clauses. (We already
+ * rejected PARTITION BY above, so no need to check that.)
+ */
+ if (windef->name ||
+ orderClause || windef->frameOptions != FRAMEOPTION_DEFAULTS)
+ ereport(ERROR,
+ (errcode(ERRCODE_WINDOWING_ERROR),
+ errmsg("cannot copy window \"%s\" because it has a frame clause",
+ windef->refname),
+ parser_errposition(pstate, windef->location)));
+ /* Else this clause is just OVER (foo), so say this: */
ereport(ERROR,
(errcode(ERRCODE_WINDOWING_ERROR),
- errmsg("cannot override frame clause of window \"%s\"",
- windef->refname),
+ errmsg("cannot copy window \"%s\" because it has a frame clause",
+ windef->refname),
+ errhint("Omit the parentheses in this OVER clause."),
parser_errposition(pstate, windef->location)));
+ }
wc->frameOptions = windef->frameOptions;
/* Process frame offset expressions */
wc->startOffset = transformFrameOffset(pstate, wc->frameOptions,