提交 f819890b 编写于 作者: H Heikki Linnakangas

Refactor window function syntax checks to match upstream.

Mostly, move the responsibilities of the check_call() function to the
callers, transformAggregateCall() and transformWindowFuncCall().

This fixes one long-standing, albeit harmless, bug. Previously, you got an
"Unexpected internal error", if you tried to use a window function in the
WHERE clause of a DELETE statement, instead of a user-friendly syntax
error. Add a test case for that.

Move a few similar tests from 'olap_window_seq' to 'qp_olap_windowerr'.
Seems like a more appropriate place for them. Also, 'olap_window_seq' has
an alternative expected output file for ORCA, so it's nice to keep tests
that produce the same output with or without ORCA out of there. Also add a
test query for creating an index on an expression containing a window
function. There was a test for that already, but it was missing parens
around the expression, and therefore produced an error already in the
grammar.
上级 63333f6d
......@@ -395,6 +395,9 @@ transformDeleteStmt(ParseState *pstate, DeleteStmt *stmt)
parseCheckAggregates(pstate, qry);
if (pstate->p_hasTblValueExpr)
parseCheckTableFunctions(pstate, qry);
qry->hasWindowFuncs = pstate->p_hasWindowFuncs;
if (pstate->p_hasWindowFuncs)
parseCheckWindowFuncs(pstate, qry);
return qry;
}
......@@ -1607,8 +1610,7 @@ transformSelectStmt(ParseState *pstate, SelectStmt *stmt)
qry->hasWindowFuncs = pstate->p_hasWindowFuncs;
if (pstate->p_hasWindowFuncs)
parseProcessWindFuncs(pstate, qry);
parseCheckWindowFuncs(pstate, qry);
foreach(l, stmt->lockingClause)
{
......@@ -2081,6 +2083,10 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt)
if (pstate->p_hasTblValueExpr)
parseCheckTableFunctions(pstate, qry);
qry->hasWindowFuncs = pstate->p_hasWindowFuncs;
if (pstate->p_hasWindowFuncs)
parseCheckWindowFuncs(pstate, qry);
foreach(l, lockingClause)
{
transformLockingClause(pstate, qry, (LockingClause *) lfirst(l));
......
......@@ -43,94 +43,63 @@ static void check_ungrouped_columns(Node *node, ParseState *pstate,
List *groupClauses, bool have_non_var_grouping);
static bool check_ungrouped_columns_walker(Node *node,
check_ungrouped_columns_context *context);
static List *check_aggregate_ingroup(Node *grpcl, ParseState *pstate,
List *targetList, List *groupClauses);
static List* get_groupclause_exprs(Node *grpcl, List *targetList);
/*
* Worker for transformAggregateCall() and transformWindowCall(). We need to
* determine which query level the aggregate or function belongs to and
* set that in the node's levelsup field. We also test some important rules:
* aggregates cannot take aggregates or window functions are arguments.
* Window functions can take aggregates as arguments but not window
* functions.
* transformAggregateCall -
* Finish initial transformation of an aggregate call
*
* parse_func.c has recognized the function as an aggregate, and has set
* up all the fields of the Aggref except agglevelsup. Here we must
* determine which query level the aggregate actually belongs to, set
* agglevelsup accordingly, and mark p_hasAggs true in the corresponding
* pstate level.
*
* GPDB: the passed-in aggorder list hasn't been transformed yet. We
* do it here.
*/
static void
check_call(ParseState *pstate, Node *call)
void
transformAggregateCall(ParseState *pstate, Aggref *agg, List *agg_order)
{
int min_varlevel = -1;
bool is_agg = IsA(call, Aggref);
int min_varlevel;
/*
* The call's level is the same as the level of the lowest-level
* The aggregate's level is the same as the level of the lowest-level
* variable or aggregate in its arguments; or if it contains no variables
* at all, we presume it to be local.
*/
if (is_agg)
min_varlevel = find_minimum_var_level((Node *) ((Aggref *)call)->args);
else
min_varlevel = find_minimum_var_level((Node *)((WindowRef *)call)->args);
min_varlevel = find_minimum_var_level((Node *) agg->args);
/*
* An aggregate can't directly contain another aggregate call of the same
* level (though outer aggs are okay). We can skip this check if we
* level (though outer aggs are okay). We can skip this check if we
* didn't find any local vars or aggs.
*/
if (min_varlevel == 0 && is_agg)
if (min_varlevel == 0)
{
Aggref *agg = (Aggref *) call;
if (checkExprHasAggs((Node *) agg->args))
if (pstate->p_hasAggs &&
checkExprHasAggs((Node *) agg->args))
ereport(ERROR,
(errcode(ERRCODE_GROUPING_ERROR),
errmsg("aggregate function calls cannot be nested"),
parser_errposition(pstate,
locate_agg_of_level((Node *) agg->args, 0))));
if (checkExprHasWindowFuncs((Node *) agg->args))
ereport(ERROR,
(errcode(ERRCODE_GROUPING_ERROR),
errmsg("window functions may not be used as arguments to aggregates")));
}
/*
* Window functions, on the other hand, may contain nested aggregates
* but not nested window refs.
*/
if (min_varlevel == 0 && !is_agg)
{
if (checkExprHasWindowFuncs((Node *)((WindowRef *)call)->args))
{
ereport(ERROR,
(errcode(ERRCODE_GROUPING_ERROR),
errmsg("cannot use window function as an argument to another window function")));
}
}
/* It can't contain window functions either */
if (pstate->p_hasWindowFuncs &&
checkExprHasWindowFuncs((Node *) agg->args))
ereport(ERROR,
(errcode(ERRCODE_GROUPING_ERROR),
errmsg("aggregate function calls cannot contain window function calls"),
parser_errposition(pstate,
locate_windowfunc((Node *) agg->args))));
if (min_varlevel < 0)
min_varlevel = 0;
agg->agglevelsup = min_varlevel;
if (is_agg)
((Aggref *)call)->agglevelsup = min_varlevel;
/* Mark the correct pstate as having aggregates */
while (min_varlevel-- > 0)
pstate = pstate->parentParseState;
if (is_agg)
pstate->p_hasAggs = true;
else
pstate->p_hasWindowFuncs = true;
}
/*
* transformAggregateCall -
* Finish initial transformation of an aggregate call
*/
void
transformAggregateCall(ParseState *pstate, Aggref *agg, List *agg_order)
{
/*
* Transform the aggregate order by, if any.
*
......@@ -175,8 +144,10 @@ transformAggregateCall(ParseState *pstate, Aggref *agg, List *agg_order)
agg->aggorder = aggorder;
}
/* shared code with window functions */
check_call(pstate, (Node *)agg);
/* Mark the correct pstate as having aggregates */
while (min_varlevel-- > 0)
pstate = pstate->parentParseState;
pstate->p_hasAggs = true;
}
void
......@@ -188,6 +159,18 @@ transformWindowFuncCall(ParseState *pstate, WindowRef *wind,
transformWindowSpec(pstate, over);
/*
* A window function call can't contain another one (but aggs are OK). XXX
* is this required by spec, or just an unimplemented feature?
*/
if (pstate->p_hasWindowFuncs &&
checkExprHasWindowFuncs((Node *) wind->args))
ereport(ERROR,
(errcode(ERRCODE_WINDOWING_ERROR),
errmsg("window function calls cannot be nested"),
parser_errposition(pstate,
locate_windowfunc((Node *) wind->args))));
/*
* Find if this "over" clause has already existed. If so,
* We let the "winspec" for this WindowRef point to
......@@ -210,8 +193,6 @@ transformWindowFuncCall(ParseState *pstate, WindowRef *wind,
pstate->p_win_clauses = lappend(pstate->p_win_clauses, over);
wind->winspec = winspec;
check_call(pstate, (Node *)wind);
pstate->p_hasWindowFuncs = true;
}
......@@ -254,7 +235,7 @@ parseCheckAggregates(ParseState *pstate, Query *qry)
}
/*
* Aggregates and window functions must never appear in WHERE or
* Aggregates and window functions must never appear in WHERE or
* JOIN/ON clauses. Window function must never appear in HAVING
* clauses.
*
......@@ -276,18 +257,6 @@ parseCheckAggregates(ParseState *pstate, Query *qry)
parser_errposition(pstate,
locate_agg_of_level((Node *) qry->jointree->fromlist, 0))));
if (checkExprHasWindowFuncs(qry->jointree->quals))
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("window functions not allowed in WHERE clause")));
if (checkExprHasWindowFuncs((Node *) qry->jointree->fromlist))
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("window functions not allowed in JOIN conditions")));
if (checkExprHasWindowFuncs((Node *) qry->havingQual))
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("window functions not allowed in HAVING conditions")));
/*
* No aggregates allowed in GROUP BY clauses, either.
*
......@@ -296,8 +265,34 @@ parseCheckAggregates(ParseState *pstate, Query *qry)
*/
foreach(l, qry->groupClause)
{
groupClauses =
check_aggregate_ingroup((Node*)lfirst(l), pstate, qry->targetList, groupClauses);
Node *grpcl = lfirst(l);
List *exprs;
ListCell *l2;
if (grpcl == NULL)
continue;
Assert(IsA(grpcl, GroupClause) || IsA(grpcl, GroupingClause));
exprs = get_groupclause_exprs(grpcl, qry->targetList);
foreach(l2, exprs)
{
Node *expr = (Node *) lfirst(l2);
if (checkExprHasAggs(expr))
ereport(ERROR,
(errcode(ERRCODE_GROUPING_ERROR),
errmsg("aggregates not allowed in GROUP BY clause"),
parser_errposition(pstate,
locate_agg_of_level(expr, 0))));
if (checkExprHasGroupExtFuncs(expr))
ereport(ERROR,
(errcode(ERRCODE_GROUPING_ERROR),
errmsg("grouping() or group_id() not allowed in GROUP BY clause")));
groupClauses = lcons(expr, groupClauses);
}
}
/*
......@@ -379,6 +374,59 @@ parseCheckAggregates(ParseState *pstate, Query *qry)
locate_agg_of_level((Node *) qry, 0))));
}
/*
* parseCheckWindowFuncs
* Check for window functions where they shouldn't be.
*
* We have to forbid window functions in WHERE, JOIN/ON, HAVING, GROUP BY,
* and window specifications. (Other clauses, such as RETURNING and LIMIT,
* have already been checked.) Transformation of all these clauses must
* be completed already.
*/
void
parseCheckWindowFuncs(ParseState *pstate, Query *qry)
{
ListCell *l;
/* This should only be called if we found window functions */
Assert(pstate->p_hasWindowFuncs);
if (checkExprHasWindowFuncs(qry->jointree->quals))
ereport(ERROR,
(errcode(ERRCODE_WINDOWING_ERROR),
errmsg("window functions not allowed in WHERE clause"),
parser_errposition(pstate,
locate_windowfunc(qry->jointree->quals))));
if (checkExprHasWindowFuncs((Node *) qry->jointree->fromlist))
ereport(ERROR,
(errcode(ERRCODE_WINDOWING_ERROR),
errmsg("window functions not allowed in JOIN conditions"),
parser_errposition(pstate,
locate_windowfunc((Node *) qry->jointree->fromlist))));
if (checkExprHasWindowFuncs(qry->havingQual))
ereport(ERROR,
(errcode(ERRCODE_WINDOWING_ERROR),
errmsg("window functions not allowed in HAVING clause"),
parser_errposition(pstate,
locate_windowfunc(qry->havingQual))));
foreach(l, qry->groupClause)
{
Node *grpcl = lfirst(l);
Node *expr;
Assert(IsA(grpcl, GroupClause) || IsA(grpcl, GroupingClause));
expr = (Node *) get_groupclause_exprs(grpcl, qry->targetList);
if (checkExprHasWindowFuncs(expr))
ereport(ERROR,
(errcode(ERRCODE_WINDOWING_ERROR),
errmsg("window functions not allowed in GROUP BY clause"),
parser_errposition(pstate,
locate_windowfunc(expr))));
}
}
/*
* check_ungrouped_columns -
......@@ -510,7 +558,6 @@ check_ungrouped_columns_walker(Node *node,
errmsg("subquery uses ungrouped column \"%s.%s\" from outer query",
rte->eref->aliasname, attname),
parser_errposition(context->pstate, var->location)));
}
if (IsA(node, Query))
......@@ -732,56 +779,6 @@ get_groupclause_exprs(Node *grpcl, List *targetList)
return result;
}
/*
* check_aggregate_ingroup -
* Check if any aggregates are appeared in a given GroupClause or
* GroupingClause. Report an error if this is the case.
*
* All relevant expressions defined in the given GroupClause or
* GroupingClause are returned as a list.
*/
static List *
check_aggregate_ingroup(Node *grpcl, ParseState *pstate, List *targetList, List *groupClauses)
{
List *exprs;
ListCell *l;
List *result = groupClauses;
if (grpcl == NULL)
return result;
Assert(IsA(grpcl, GroupClause) || IsA(grpcl, GroupingClause));
exprs = get_groupclause_exprs(grpcl, targetList);
foreach(l, exprs)
{
Node *expr = (Node*)lfirst(l);
if (expr == NULL)
continue; /* probably cannot happen */
if (checkExprHasAggs(expr))
ereport(ERROR,
(errcode(ERRCODE_GROUPING_ERROR),
errmsg("aggregates not allowed in GROUP BY clause"),
parser_errposition(pstate,
locate_agg_of_level(expr, 0))));
if (checkExprHasGroupExtFuncs(expr))
ereport(ERROR,
(errcode(ERRCODE_GROUPING_ERROR),
errmsg("grouping() or group_id() not allowed in GROUP BY clause")));
if (checkExprHasWindowFuncs(expr))
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("window functions not allowed in GROUP BY clause")));
result = lcons(expr, result);
}
return result;
}
static bool
checkExprHasGroupExtFuncs_walker(Node *node, checkHasGroupExtFuncs_context *context)
{
......@@ -905,36 +902,3 @@ transformWindowSpecExprs(ParseState *pstate)
transformWindowSpec(pstate, s);
}
}
/*
* parseProcessWindFuncs
*
* Do some final checks on window functions and do post processing
* on queries with grouping and window functions.
*/
void
parseProcessWindFuncs(ParseState *pstate, Query *qry)
{
/* This should only be called if we found window functions */
Assert(pstate->p_hasWindowFuncs);
/*
* Window functions must never appear in WHERE or
* JOIN/ON clauses.
*
* (Note this check should appear first to deliver an appropriate error
* message; otherwise we are likely to complain about some innocent
* variable in the target list, which is outright misleading if the
* problem is in WHERE.)
*/
if (checkExprHasWindowFuncs(qry->jointree->quals))
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("window functions not allowed in WHERE clause")));
/* if (checkExprHasAggs((Node *) qry->jointree->fromlist)) */
if (checkExprHasWindowFuncs((Node *) qry->jointree->fromlist))
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("window functions not allowed in JOIN conditions")));
}
......@@ -20,7 +20,7 @@ extern void transformAggregateCall(ParseState *pstate, Aggref *agg,
extern void transformWindowFuncCall(ParseState *pstate, WindowRef *wind, WindowSpec *over);
extern void parseCheckAggregates(ParseState *pstate, Query *qry);
extern void parseProcessWindFuncs(ParseState *pstate, Query *qry);
extern void parseCheckWindowFuncs(ParseState *pstate, Query *qry);
extern void transformWindowSpec(ParseState *pstate, WindowSpec *spec);
extern void transformWindowSpecExprs(ParseState *pstate);
......
......@@ -7615,44 +7615,11 @@ select ord, cn,vn,sum(vn) over (order by ord rows between 3 following and floor(
12 | 4 | 40 |
(12 rows)
-- Test use of window functions in places they shouldn't be allowed: MPP-2382
-- CHECK constraints
CREATE TABLE wintest_for_window_seq (i int check (i < count(*) over (order by i)));
NOTICE: Table doesn't have 'DISTRIBUTED BY' clause -- Using column named 'i' as the Greenplum Database data distribution key for this table.
HINT: The 'DISTRIBUTED BY' clause determines the distribution of data. Make sure column(s) chosen are the optimal data distribution key to minimize skew.
ERROR: cannot use window function in check constraint
CREATE TABLE wintest_for_window_seq (i int default count(*) over (order by i));
NOTICE: Table doesn't have 'DISTRIBUTED BY' clause -- Using column named 'i' as the Greenplum Database data distribution key for this table.
HINT: The 'DISTRIBUTED BY' clause determines the distribution of data. Make sure column(s) chosen are the optimal data distribution key to minimize skew.
ERROR: cannot use window function in default expression
-- index expression and function
CREATE TABLE wintest_for_window_seq (i int);
NOTICE: Table doesn't have 'DISTRIBUTED BY' clause -- Using column named 'i' as the Greenplum Database data distribution key for this table.
HINT: The 'DISTRIBUTED BY' clause determines the distribution of data. Make sure column(s) chosen are the optimal data distribution key to minimize skew.
CREATE INDEX wintest_idx_for_window_seq on wintest_for_window_seq (i) where i < count(*) over (order by i);
ERROR: cannot use window function in index predicate
CREATE INDEX wintest_idx_for_window_seq on wintest_for_window_seq (sum(i) over (order by i));
ERROR: syntax error at or near "("
LINE 1: ...window_seq on wintest_for_window_seq (sum(i) over (order by ...
^
-- alter table
ALTER TABLE wintest_for_window_seq alter i set default count(*) over (order by i);
ERROR: cannot use window function in default expression
alter table wintest_for_window_seq alter column i type float using count(*) over (order by
i)::float;
ERROR: cannot use window function in transform expression
-- update
insert into wintest_for_window_seq values(1);
update wintest_for_window_seq set i = count(*) over (order by i);
ERROR: cannot use window function in UPDATE
LINE 1: update wintest_for_window_seq set i = count(*) over (order b...
^
-- domain suport
create domain wintestd as int default count(*) over ();
ERROR: cannot use window function in default expression
create domain wintestd as int check (value < count(*) over ());
ERROR: cannot use window function in check constraint
drop table wintest_for_window_seq;
-- MPP-3295
-- begin equivalent
select cn,vn,rank() over (partition by cn order by vn) as rank
......
......@@ -7617,44 +7617,11 @@ select ord, cn,vn,sum(vn) over (order by ord rows between 3 following and floor(
12 | 4 | 40 |
(12 rows)
-- Test use of window functions in places they shouldn't be allowed: MPP-2382
-- CHECK constraints
CREATE TABLE wintest_for_window_seq (i int check (i < count(*) over (order by i)));
NOTICE: Table doesn't have 'DISTRIBUTED BY' clause -- Using column named 'i' as the Greenplum Database data distribution key for this table.
HINT: The 'DISTRIBUTED BY' clause determines the distribution of data. Make sure column(s) chosen are the optimal data distribution key to minimize skew.
ERROR: cannot use window function in check constraint
CREATE TABLE wintest_for_window_seq (i int default count(*) over (order by i));
NOTICE: Table doesn't have 'DISTRIBUTED BY' clause -- Using column named 'i' as the Greenplum Database data distribution key for this table.
HINT: The 'DISTRIBUTED BY' clause determines the distribution of data. Make sure column(s) chosen are the optimal data distribution key to minimize skew.
ERROR: cannot use window function in default expression
-- index expression and function
CREATE TABLE wintest_for_window_seq (i int);
NOTICE: Table doesn't have 'DISTRIBUTED BY' clause -- Using column named 'i' as the Greenplum Database data distribution key for this table.
HINT: The 'DISTRIBUTED BY' clause determines the distribution of data. Make sure column(s) chosen are the optimal data distribution key to minimize skew.
CREATE INDEX wintest_idx_for_window_seq on wintest_for_window_seq (i) where i < count(*) over (order by i);
ERROR: cannot use window function in index predicate
CREATE INDEX wintest_idx_for_window_seq on wintest_for_window_seq (sum(i) over (order by i));
ERROR: syntax error at or near "("
LINE 1: ...window_seq on wintest_for_window_seq (sum(i) over (order by ...
^
-- alter table
ALTER TABLE wintest_for_window_seq alter i set default count(*) over (order by i);
ERROR: cannot use window function in default expression
alter table wintest_for_window_seq alter column i type float using count(*) over (order by
i)::float;
ERROR: cannot use window function in transform expression
-- update
insert into wintest_for_window_seq values(1);
update wintest_for_window_seq set i = count(*) over (order by i);
ERROR: cannot use window function in UPDATE
LINE 1: update wintest_for_window_seq set i = count(*) over (order b...
^
-- domain suport
create domain wintestd as int default count(*) over ();
ERROR: cannot use window function in default expression
create domain wintestd as int check (value < count(*) over ());
ERROR: cannot use window function in check constraint
drop table wintest_for_window_seq;
-- MPP-3295
-- begin equivalent
select cn,vn,rank() over (partition by cn order by vn) as rank
......
......@@ -3404,9 +3404,60 @@ ERROR: argument value out of range
HINT: NTILE expects a positive integer argument.
-- start_ignore
DROP TABLE filter_test;
-- end_ignore
-- Test use of window functions in places they shouldn't be allowed: MPP-2382
-- CHECK constraints
CREATE TABLE wintest_for_window_seq (i int check (i < count(*) over (order by i)));
NOTICE: Table doesn't have 'DISTRIBUTED BY' clause -- Using column named 'i' as the Greenplum Database data distribution key for this table.
HINT: The 'DISTRIBUTED BY' clause determines the distribution of data. Make sure column(s) chosen are the optimal data distribution key to minimize skew.
ERROR: cannot use window function in check constraint
CREATE TABLE wintest_for_window_seq (i int default count(*) over (order by i));
NOTICE: Table doesn't have 'DISTRIBUTED BY' clause -- Using column named 'i' as the Greenplum Database data distribution key for this table.
HINT: The 'DISTRIBUTED BY' clause determines the distribution of data. Make sure column(s) chosen are the optimal data distribution key to minimize skew.
ERROR: cannot use window function in default expression
-- index expression and function
CREATE TABLE wintest_for_window_seq (i int);
NOTICE: Table doesn't have 'DISTRIBUTED BY' clause -- Using column named 'i' as the Greenplum Database data distribution key for this table.
HINT: The 'DISTRIBUTED BY' clause determines the distribution of data. Make sure column(s) chosen are the optimal data distribution key to minimize skew.
insert into wintest_for_window_seq values(1);
CREATE INDEX wintest_idx_for_window_seq on wintest_for_window_seq (i) where i < count(*) over (order by i);
ERROR: cannot use window function in index predicate
CREATE INDEX wintest_idx_for_window_seq on wintest_for_window_seq (sum(i) over (order by i));
ERROR: syntax error at or near "("
LINE 1: ...window_seq on wintest_for_window_seq (sum(i) over (order by ...
^
CREATE INDEX wintest_idx_for_window_seq on wintest_for_window_seq ((sum(i) over (order by i)));
ERROR: cannot use window function in index expression
-- alter table
ALTER TABLE wintest_for_window_seq alter i set default count(*) over (order by i);
ERROR: cannot use window function in default expression
alter table wintest_for_window_seq alter column i type float using count(*) over (order by
i)::float;
ERROR: cannot use window function in transform expression
-- select
select * from wintest_for_window_seq where count(*) over (order by i) > 0;
ERROR: window functions not allowed in WHERE clause
LINE 1: select * from wintest_for_window_seq where count(*) over (or...
^
-- update
update wintest_for_window_seq set i = count(*) over (order by i);
ERROR: cannot use window function in UPDATE
LINE 1: update wintest_for_window_seq set i = count(*) over (order b...
^
update wintest_for_window_seq set i = 1 where count(*) over (order by i) > 0;
ERROR: cannot use window function in UPDATE
LINE 1: update wintest_for_window_seq set i = 1 where count(*) over ...
^
-- delete
delete from wintest_for_window_seq where count(*) over (order by i) > 0;
ERROR: window functions not allowed in WHERE clause
LINE 1: delete from wintest_for_window_seq where count(*) over (orde...
^
drop table wintest_for_window_seq;
--
-- STANDARD DATA FOR olap_* TESTS.
--
-- start_ignore
drop table cf_olap_windowerr_customer;
drop table cf_olap_windowerr_vendor;
drop table cf_olap_windowerr_product;
......
......@@ -1317,31 +1317,10 @@ select ord, pn,cn,vn,sum(vn) over (order by ord, pn rows between cn following an
-- MPP-2323
select ord, cn,vn,sum(vn) over (order by ord rows between 3 following and floor(cn) following ) from sale_ord;
-- Test use of window functions in places they shouldn't be allowed: MPP-2382
-- CHECK constraints
CREATE TABLE wintest_for_window_seq (i int check (i < count(*) over (order by i)));
CREATE TABLE wintest_for_window_seq (i int default count(*) over (order by i));
-- index expression and function
CREATE TABLE wintest_for_window_seq (i int);
CREATE INDEX wintest_idx_for_window_seq on wintest_for_window_seq (i) where i < count(*) over (order by i);
CREATE INDEX wintest_idx_for_window_seq on wintest_for_window_seq (sum(i) over (order by i));
-- alter table
ALTER TABLE wintest_for_window_seq alter i set default count(*) over (order by i);
alter table wintest_for_window_seq alter column i type float using count(*) over (order by
i)::float;
-- update
insert into wintest_for_window_seq values(1);
update wintest_for_window_seq set i = count(*) over (order by i);
-- domain suport
create domain wintestd as int default count(*) over ();
create domain wintestd as int check (value < count(*) over ());
drop table wintest_for_window_seq;
-- MPP-3295
-- begin equivalent
select cn,vn,rank() over (partition by cn order by vn) as rank
......
......@@ -3729,10 +3729,43 @@ SELECT ntile(0) over (order by i) FROM filter_test;
-- start_ignore
DROP TABLE filter_test;
-- end_ignore
-- Test use of window functions in places they shouldn't be allowed: MPP-2382
-- CHECK constraints
CREATE TABLE wintest_for_window_seq (i int check (i < count(*) over (order by i)));
CREATE TABLE wintest_for_window_seq (i int default count(*) over (order by i));
-- index expression and function
CREATE TABLE wintest_for_window_seq (i int);
insert into wintest_for_window_seq values(1);
CREATE INDEX wintest_idx_for_window_seq on wintest_for_window_seq (i) where i < count(*) over (order by i);
CREATE INDEX wintest_idx_for_window_seq on wintest_for_window_seq (sum(i) over (order by i));
CREATE INDEX wintest_idx_for_window_seq on wintest_for_window_seq ((sum(i) over (order by i)));
-- alter table
ALTER TABLE wintest_for_window_seq alter i set default count(*) over (order by i);
alter table wintest_for_window_seq alter column i type float using count(*) over (order by
i)::float;
-- select
select * from wintest_for_window_seq where count(*) over (order by i) > 0;
-- update
update wintest_for_window_seq set i = count(*) over (order by i);
update wintest_for_window_seq set i = 1 where count(*) over (order by i) > 0;
-- delete
delete from wintest_for_window_seq where count(*) over (order by i) > 0;
drop table wintest_for_window_seq;
--
-- STANDARD DATA FOR olap_* TESTS.
--
-- start_ignore
drop table cf_olap_windowerr_customer;
drop table cf_olap_windowerr_vendor;
drop table cf_olap_windowerr_product;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册