提交 3fc342d6 编写于 作者: H Heikki Linnakangas

Cherry-pick locate_windowfunc() from PostgreSQL 8.4.

This allows having error positions for more syntax errors, and reduces
the diff footprint of our window functions implementation against the
one in PostgreSQL 8.4.
上级 931d5d57
...@@ -812,7 +812,9 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt) ...@@ -812,7 +812,9 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt)
if (pstate->p_hasWindowFuncs) if (pstate->p_hasWindowFuncs)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_WINDOWING_ERROR), (errcode(ERRCODE_WINDOWING_ERROR),
errmsg("cannot use window function in VALUES"))); errmsg("cannot use window function in VALUES"),
parser_errposition(pstate,
locate_windowfunc((Node *) qry))));
return qry; return qry;
} }
...@@ -1885,7 +1887,9 @@ transformValuesClause(ParseState *pstate, SelectStmt *stmt) ...@@ -1885,7 +1887,9 @@ transformValuesClause(ParseState *pstate, SelectStmt *stmt)
if (pstate->p_hasWindowFuncs) if (pstate->p_hasWindowFuncs)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_WINDOWING_ERROR), (errcode(ERRCODE_WINDOWING_ERROR),
errmsg("cannot use window function in VALUES"))); errmsg("cannot use window function in VALUES"),
parser_errposition(pstate,
locate_windowfunc((Node *) newExprsLists))));
return qry; return qry;
} }
...@@ -2747,7 +2751,9 @@ transformUpdateStmt(ParseState *pstate, UpdateStmt *stmt) ...@@ -2747,7 +2751,9 @@ transformUpdateStmt(ParseState *pstate, UpdateStmt *stmt)
if (pstate->p_hasWindowFuncs) if (pstate->p_hasWindowFuncs)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_WINDOWING_ERROR), (errcode(ERRCODE_WINDOWING_ERROR),
errmsg("cannot use window function in UPDATE"))); errmsg("cannot use window function in UPDATE"),
parser_errposition(pstate,
locate_windowfunc((Node *) qry))));
/* /*
* Now we are done with SELECT-like processing, and can get on with * Now we are done with SELECT-like processing, and can get on with
...@@ -2855,9 +2861,10 @@ transformReturningList(ParseState *pstate, List *returningList) ...@@ -2855,9 +2861,10 @@ transformReturningList(ParseState *pstate, List *returningList)
if (pstate->p_hasWindowFuncs) if (pstate->p_hasWindowFuncs)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR), (errcode(ERRCODE_WINDOWING_ERROR),
errmsg("cannot use window function in RETURNING"))); errmsg("cannot use window function in RETURNING"),
parser_errposition(pstate,
locate_windowfunc((Node *) rlist))));
/* no new relation references please */ /* no new relation references please */
if (list_length(pstate->p_rtable) != length_rtable) if (list_length(pstate->p_rtable) != length_rtable)
......
...@@ -457,11 +457,12 @@ transformWindowClause(ParseState *pstate, Query *qry) ...@@ -457,11 +457,12 @@ transformWindowClause(ParseState *pstate, Query *qry)
clauseno++; clauseno++;
if (checkExprHasWindowFuncs((Node *)ws)) if (checkExprHasWindowFuncs((Node *) ws))
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR), (errcode(ERRCODE_WINDOWING_ERROR),
errmsg("cannot use window function in a window specification"), errmsg("cannot use window function in a window specification"),
parser_errposition(pstate, ws->location))); parser_errposition(pstate,
locate_windowfunc((Node *) ws))));
/* /*
* Loop through those clauses we've already processed to * Loop through those clauses we've already processed to
......
...@@ -2271,7 +2271,8 @@ transformPercentileExpr(ParseState *pstate, PercentileExpr *p) ...@@ -2271,7 +2271,8 @@ transformPercentileExpr(ParseState *pstate, PercentileExpr *p)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_GROUPING_ERROR), (errcode(ERRCODE_GROUPING_ERROR),
errmsg("argument of percentile function must not contain window functions"), errmsg("argument of percentile function must not contain window functions"),
parser_errposition(pstate, exprLocation(arg)))); parser_errposition(pstate,
locate_windowfunc(arg))));
if (checkExprHasGroupExtFuncs(arg)) if (checkExprHasGroupExtFuncs(arg))
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_GROUPING_ERROR), (errcode(ERRCODE_GROUPING_ERROR),
...@@ -2479,7 +2480,8 @@ transformPercentileExpr(ParseState *pstate, PercentileExpr *p) ...@@ -2479,7 +2480,8 @@ transformPercentileExpr(ParseState *pstate, PercentileExpr *p)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_GROUPING_ERROR), (errcode(ERRCODE_GROUPING_ERROR),
errmsg("argument of percentile function must not contain window functions"), errmsg("argument of percentile function must not contain window functions"),
parser_errposition(pstate, exprLocation((Node *) p->sortTargets)))); parser_errposition(pstate,
locate_windowfunc((Node *) p->sortTargets))));
if (checkExprHasGroupExtFuncs((Node *) p->sortTargets)) if (checkExprHasGroupExtFuncs((Node *) p->sortTargets))
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_GROUPING_ERROR), (errcode(ERRCODE_GROUPING_ERROR),
......
...@@ -35,11 +35,18 @@ typedef struct ...@@ -35,11 +35,18 @@ typedef struct
int sublevels_up; int sublevels_up;
} locate_agg_of_level_context; } locate_agg_of_level_context;
typedef struct
{
int win_location;
} locate_windowfunc_context;
static bool checkExprHasAggs_walker(Node *node, static bool checkExprHasAggs_walker(Node *node,
checkExprHasAggs_context *context); checkExprHasAggs_context *context);
static bool locate_agg_of_level_walker(Node *node, static bool locate_agg_of_level_walker(Node *node,
locate_agg_of_level_context *context); locate_agg_of_level_context *context);
static bool contain_windowfuncs_walker(Node *node, void *context); static bool contain_windowfuncs_walker(Node *node, void *context);
static bool locate_windowfunc_walker(Node *node,
locate_windowfunc_context *context);
static bool checkExprHasSubLink_walker(Node *node, void *context); static bool checkExprHasSubLink_walker(Node *node, void *context);
static Relids offset_relid_set(Relids relids, int offset); static Relids offset_relid_set(Relids relids, int offset);
static Relids adjust_relid_set(Relids relids, int oldrelid, int newrelid); static Relids adjust_relid_set(Relids relids, int oldrelid, int newrelid);
...@@ -262,6 +269,57 @@ contain_windowfuncs_walker(Node *node, void *context) ...@@ -262,6 +269,57 @@ contain_windowfuncs_walker(Node *node, void *context)
(void *) context); (void *) context);
} }
/*
* locate_windowfunc -
* Find the parse location of any windowfunc of the current query level.
*
* Returns -1 if no such windowfunc is in the querytree, or if they all have
* unknown parse location. (The former case is probably caller error,
* but we don't bother to distinguish it from the latter case.)
*
* Note: it might seem appropriate to merge this functionality into
* contain_windowfuncs, but that would complicate that function's API.
* Currently, the only uses of this function are for error reporting,
* and so shaving cycles probably isn't very important.
*/
int
locate_windowfunc(Node *node)
{
locate_windowfunc_context context;
context.win_location = -1; /* in case we find nothing */
/*
* Must be prepared to start with a Query or a bare expression tree; if
* it's a Query, we don't want to increment sublevels_up.
*/
(void) query_or_expression_tree_walker(node,
locate_windowfunc_walker,
(void *) &context,
0);
return context.win_location;
}
static bool
locate_windowfunc_walker(Node *node, locate_windowfunc_context *context)
{
if (node == NULL)
return false;
if (IsA(node, WindowRef))
{
if (((WindowRef *) node)->location >= 0)
{
context->win_location = ((WindowRef *) node)->location;
return true; /* abort the tree traversal and return true */
}
/* else fall through to examine argument */
}
/* Mustn't recurse into subselects */
return expression_tree_walker(node, locate_windowfunc_walker,
(void *) context);
}
/* /*
* checkExprHasSubLink - * checkExprHasSubLink -
* Check if an expression contains a SubLink. * Check if an expression contains a SubLink.
......
...@@ -38,6 +38,7 @@ extern void AddQual(Query *parsetree, Node *qual); ...@@ -38,6 +38,7 @@ extern void AddQual(Query *parsetree, Node *qual);
extern void AddInvertedQual(Query *parsetree, Node *qual); extern void AddInvertedQual(Query *parsetree, Node *qual);
extern int locate_agg_of_level(Node *node, int levelsup); extern int locate_agg_of_level(Node *node, int levelsup);
extern int locate_windowfunc(Node *node);
extern bool checkExprHasAggs(Node *node); extern bool checkExprHasAggs(Node *node);
extern bool checkExprHasWindowFuncs(Node *node); extern bool checkExprHasWindowFuncs(Node *node);
extern bool checkExprHasSubLink(Node *node); extern bool checkExprHasSubLink(Node *node);
......
...@@ -7643,6 +7643,8 @@ ERROR: cannot use window function in transform expression ...@@ -7643,6 +7643,8 @@ ERROR: cannot use window function in transform expression
insert into wintest_for_window_seq values(1); insert into wintest_for_window_seq values(1);
update wintest_for_window_seq set i = count(*) over (order by i); update wintest_for_window_seq set i = count(*) over (order by i);
ERROR: cannot use window function in UPDATE ERROR: cannot use window function in UPDATE
LINE 1: update wintest_for_window_seq set i = count(*) over (order b...
^
-- domain suport -- domain suport
create domain wintestd as int default count(*) over (); create domain wintestd as int default count(*) over ();
ERROR: cannot use window function in default expression ERROR: cannot use window function in default expression
......
...@@ -7645,6 +7645,8 @@ ERROR: cannot use window function in transform expression ...@@ -7645,6 +7645,8 @@ ERROR: cannot use window function in transform expression
insert into wintest_for_window_seq values(1); insert into wintest_for_window_seq values(1);
update wintest_for_window_seq set i = count(*) over (order by i); update wintest_for_window_seq set i = count(*) over (order by i);
ERROR: cannot use window function in UPDATE ERROR: cannot use window function in UPDATE
LINE 1: update wintest_for_window_seq set i = count(*) over (order b...
^
-- domain suport -- domain suport
create domain wintestd as int default count(*) over (); create domain wintestd as int default count(*) over ();
ERROR: cannot use window function in default expression ERROR: cannot use window function in default expression
......
...@@ -1041,7 +1041,7 @@ LINE 1: select median(count(*)) from perct; ...@@ -1041,7 +1041,7 @@ LINE 1: select median(count(*)) from perct;
^ ^
select percentile_cont(0.2) within group (order by count(*) over()) from perct; select percentile_cont(0.2) within group (order by count(*) over()) from perct;
ERROR: argument of percentile function must not contain window functions ERROR: argument of percentile function must not contain window functions
LINE 1: select percentile_cont(0.2) within group (order by count(*) ... LINE 1: ...elect percentile_cont(0.2) within group (order by count(*) o...
^ ^
select percentile_disc(0.1) within group (order by group_id()) from perct; select percentile_disc(0.1) within group (order by group_id()) from perct;
ERROR: argument of percentile function must not contain grouping(), or group_id() ERROR: argument of percentile function must not contain grouping(), or group_id()
......
...@@ -676,7 +676,7 @@ ERROR: window OVER clause can only be used with an aggregate ...@@ -676,7 +676,7 @@ ERROR: window OVER clause can only be used with an aggregate
-- SQL with IDF , aggregate func and over clause within IDF : ERROR -- SQL with IDF , aggregate func and over clause within IDF : ERROR
select percentile_cont(0.2) within group (order by stddev(b) over() ) from perct; select percentile_cont(0.2) within group (order by stddev(b) over() ) from perct;
ERROR: argument of percentile function must not contain window functions ERROR: argument of percentile function must not contain window functions
LINE 1: select percentile_cont(0.2) within group (order by stddev(b)... LINE 1: ...elect percentile_cont(0.2) within group (order by stddev(b) ...
^ ^
select median(avg(a) over()) from perct; select median(avg(a) over()) from perct;
ERROR: argument of percentile function must not contain window functions ERROR: argument of percentile function must not contain window functions
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册