1
0
mirror of https://github.com/postgres/postgres.git synced 2025-06-26 12:21:12 +03:00

Support window functions a la SQL:2008.

Hitoshi Harada, with some kibitzing from Heikki and Tom.
This commit is contained in:
Tom Lane
2008-12-28 18:54:01 +00:00
parent 38e9348282
commit 95b07bc7f5
92 changed files with 6720 additions and 321 deletions

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/nodes/nodeFuncs.c,v 1.35 2008/10/21 20:42:52 tgl Exp $
* $PostgreSQL: pgsql/src/backend/nodes/nodeFuncs.c,v 1.36 2008/12/28 18:53:56 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -52,6 +52,9 @@ exprType(Node *expr)
case T_Aggref:
type = ((Aggref *) expr)->aggtype;
break;
case T_WindowFunc:
type = ((WindowFunc *) expr)->wintype;
break;
case T_ArrayRef:
{
ArrayRef *arrayref = (ArrayRef *) expr;
@ -548,6 +551,8 @@ expression_returns_set_walker(Node *node, void *context)
/* Avoid recursion for some cases that can't return a set */
if (IsA(node, Aggref))
return false;
if (IsA(node, WindowFunc))
return false;
if (IsA(node, DistinctExpr))
return false;
if (IsA(node, ScalarArrayOpExpr))
@ -634,6 +639,10 @@ exprLocation(Node *expr)
/* function name should always be the first thing */
loc = ((Aggref *) expr)->location;
break;
case T_WindowFunc:
/* function name should always be the first thing */
loc = ((WindowFunc *) expr)->location;
break;
case T_ArrayRef:
/* just use array argument's location */
loc = exprLocation((Node *) ((ArrayRef *) expr)->refexpr);
@ -868,6 +877,9 @@ exprLocation(Node *expr)
/* just use argument's location (ignore operator, if any) */
loc = exprLocation(((SortBy *) expr)->node);
break;
case T_WindowDef:
loc = ((WindowDef *) expr)->location;
break;
case T_TypeName:
loc = ((TypeName *) expr)->location;
break;
@ -1045,6 +1057,16 @@ expression_tree_walker(Node *node,
return true;
}
break;
case T_WindowFunc:
{
WindowFunc *expr = (WindowFunc *) node;
/* recurse directly on List */
if (expression_tree_walker((Node *) expr->args,
walker, context))
return true;
}
break;
case T_ArrayRef:
{
ArrayRef *aref = (ArrayRef *) node;
@ -1221,6 +1243,16 @@ expression_tree_walker(Node *node,
case T_Query:
/* Do nothing with a sub-Query, per discussion above */
break;
case T_WindowClause:
{
WindowClause *wc = (WindowClause *) node;
if (walker(wc->partitionClause, context))
return true;
if (walker(wc->orderClause, context))
return true;
}
break;
case T_CommonTableExpr:
{
CommonTableExpr *cte = (CommonTableExpr *) node;
@ -1539,6 +1571,16 @@ expression_tree_mutator(Node *node,
return (Node *) newnode;
}
break;
case T_WindowFunc:
{
WindowFunc *wfunc = (WindowFunc *) node;
WindowFunc *newnode;
FLATCOPY(newnode, wfunc, WindowFunc);
MUTATE(newnode->args, wfunc->args, List *);
return (Node *) newnode;
}
break;
case T_ArrayRef:
{
ArrayRef *arrayref = (ArrayRef *) node;
@ -1848,6 +1890,17 @@ expression_tree_mutator(Node *node,
case T_Query:
/* Do nothing with a sub-Query, per discussion above */
return node;
case T_WindowClause:
{
WindowClause *wc = (WindowClause *) node;
WindowClause *newnode;
FLATCOPY(newnode, wc, WindowClause);
MUTATE(newnode->partitionClause, wc->partitionClause, List *);
MUTATE(newnode->orderClause, wc->orderClause, List *);
return (Node *) newnode;
}
break;
case T_CommonTableExpr:
{
CommonTableExpr *cte = (CommonTableExpr *) node;
@ -2280,6 +2333,8 @@ raw_expression_tree_walker(Node *node, bool (*walker) (), void *context)
return true;
if (walker(stmt->havingClause, context))
return true;
if (walker(stmt->windowClause, context))
return true;
if (walker(stmt->withClause, context))
return true;
if (walker(stmt->valuesLists, context))
@ -2318,6 +2373,8 @@ raw_expression_tree_walker(Node *node, bool (*walker) (), void *context)
if (walker(fcall->args, context))
return true;
if (walker(fcall->over, context))
return true;
/* function name is deemed uninteresting */
}
break;
@ -2365,6 +2422,16 @@ raw_expression_tree_walker(Node *node, bool (*walker) (), void *context)
break;
case T_SortBy:
return walker(((SortBy *) node)->node, context);
case T_WindowDef:
{
WindowDef *wd = (WindowDef *) node;
if (walker(wd->partitionClause, context))
return true;
if (walker(wd->orderClause, context))
return true;
}
break;
case T_RangeSubselect:
{
RangeSubselect *rs = (RangeSubselect *) node;