1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-05 07:21:24 +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

@ -4,7 +4,7 @@
# Makefile for executor
#
# IDENTIFICATION
# $PostgreSQL: pgsql/src/backend/executor/Makefile,v 1.28 2008/10/04 21:56:52 tgl Exp $
# $PostgreSQL: pgsql/src/backend/executor/Makefile,v 1.29 2008/12/28 18:53:55 tgl Exp $
#
#-------------------------------------------------------------------------
@ -22,6 +22,6 @@ OBJS = execAmi.o execCurrent.o execGrouping.o execJunk.o execMain.o \
nodeSeqscan.o nodeSetOp.o nodeSort.o nodeUnique.o \
nodeValuesscan.o nodeCtescan.o nodeWorktablescan.o \
nodeLimit.o nodeGroup.o nodeSubplan.o nodeSubqueryscan.o nodeTidscan.o \
tstoreReceiver.o spi.o
nodeWindowAgg.o tstoreReceiver.o spi.o
include $(top_srcdir)/src/backend/common.mk

View File

@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/backend/executor/execAmi.c,v 1.101 2008/10/28 17:13:51 tgl Exp $
* $PostgreSQL: pgsql/src/backend/executor/execAmi.c,v 1.102 2008/12/28 18:53:55 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -20,6 +20,7 @@
#include "executor/nodeBitmapHeapscan.h"
#include "executor/nodeBitmapIndexscan.h"
#include "executor/nodeBitmapOr.h"
#include "executor/nodeCtescan.h"
#include "executor/nodeFunctionscan.h"
#include "executor/nodeGroup.h"
#include "executor/nodeGroup.h"
@ -40,7 +41,7 @@
#include "executor/nodeTidscan.h"
#include "executor/nodeUnique.h"
#include "executor/nodeValuesscan.h"
#include "executor/nodeCtescan.h"
#include "executor/nodeWindowAgg.h"
#include "executor/nodeWorktablescan.h"
#include "nodes/nodeFuncs.h"
#include "utils/syscache.h"
@ -210,6 +211,10 @@ ExecReScan(PlanState *node, ExprContext *exprCtxt)
ExecReScanAgg((AggState *) node, exprCtxt);
break;
case T_WindowAggState:
ExecReScanWindowAgg((WindowAggState *) node, exprCtxt);
break;
case T_UniqueState:
ExecReScanUnique((UniqueState *) node, exprCtxt);
break;

View File

@ -12,7 +12,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/executor/execProcnode.c,v 1.63 2008/10/04 21:56:53 tgl Exp $
* $PostgreSQL: pgsql/src/backend/executor/execProcnode.c,v 1.64 2008/12/28 18:53:55 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -85,6 +85,7 @@
#include "executor/nodeBitmapHeapscan.h"
#include "executor/nodeBitmapIndexscan.h"
#include "executor/nodeBitmapOr.h"
#include "executor/nodeCtescan.h"
#include "executor/nodeFunctionscan.h"
#include "executor/nodeGroup.h"
#include "executor/nodeHash.h"
@ -104,7 +105,7 @@
#include "executor/nodeTidscan.h"
#include "executor/nodeUnique.h"
#include "executor/nodeValuesscan.h"
#include "executor/nodeCtescan.h"
#include "executor/nodeWindowAgg.h"
#include "executor/nodeWorktablescan.h"
#include "miscadmin.h"
@ -260,6 +261,11 @@ ExecInitNode(Plan *node, EState *estate, int eflags)
estate, eflags);
break;
case T_WindowAgg:
result = (PlanState *) ExecInitWindowAgg((WindowAgg *) node,
estate, eflags);
break;
case T_Unique:
result = (PlanState *) ExecInitUnique((Unique *) node,
estate, eflags);
@ -425,6 +431,10 @@ ExecProcNode(PlanState *node)
result = ExecAgg((AggState *) node);
break;
case T_WindowAggState:
result = ExecWindowAgg((WindowAggState *) node);
break;
case T_UniqueState:
result = ExecUnique((UniqueState *) node);
break;
@ -601,6 +611,10 @@ ExecCountSlotsNode(Plan *node)
case T_Agg:
return ExecCountSlotsAgg((Agg *) node);
case T_WindowAgg:
return ExecCountSlotsWindowAgg((WindowAgg *) node);
break;
case T_Unique:
return ExecCountSlotsUnique((Unique *) node);
@ -749,6 +763,10 @@ ExecEndNode(PlanState *node)
ExecEndAgg((AggState *) node);
break;
case T_WindowAggState:
ExecEndWindowAgg((WindowAggState *) node);
break;
case T_UniqueState:
ExecEndUnique((UniqueState *) node);
break;

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.238 2008/12/18 19:38:22 tgl Exp $
* $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.239 2008/12/28 18:53:55 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -62,6 +62,9 @@ static Datum ExecEvalArrayRef(ArrayRefExprState *astate,
static Datum ExecEvalAggref(AggrefExprState *aggref,
ExprContext *econtext,
bool *isNull, ExprDoneCond *isDone);
static Datum ExecEvalWindowFunc(WindowFuncExprState *wfunc,
ExprContext *econtext,
bool *isNull, ExprDoneCond *isDone);
static Datum ExecEvalVar(ExprState *exprstate, ExprContext *econtext,
bool *isNull, ExprDoneCond *isDone);
static Datum ExecEvalScalarVar(ExprState *exprstate, ExprContext *econtext,
@ -443,6 +446,27 @@ ExecEvalAggref(AggrefExprState *aggref, ExprContext *econtext,
return econtext->ecxt_aggvalues[aggref->aggno];
}
/* ----------------------------------------------------------------
* ExecEvalWindowFunc
*
* Returns a Datum whose value is the value of the precomputed
* window function found in the given expression context.
* ----------------------------------------------------------------
*/
static Datum
ExecEvalWindowFunc(WindowFuncExprState *wfunc, ExprContext *econtext,
bool *isNull, ExprDoneCond *isDone)
{
if (isDone)
*isDone = ExprSingleResult;
if (econtext->ecxt_aggvalues == NULL) /* safety check */
elog(ERROR, "no window functions in this expression context");
*isNull = econtext->ecxt_aggnulls[wfunc->wfuncno];
return econtext->ecxt_aggvalues[wfunc->wfuncno];
}
/* ----------------------------------------------------------------
* ExecEvalVar
*
@ -4062,12 +4086,12 @@ ExecEvalExprSwitchContext(ExprState *expression,
* executions of the expression are needed. Typically the context will be
* the same as the per-query context of the associated ExprContext.
*
* Any Aggref and SubPlan nodes found in the tree are added to the lists
* of such nodes held by the parent PlanState. Otherwise, we do very little
* initialization here other than building the state-node tree. Any nontrivial
* work associated with initializing runtime info for a node should happen
* during the first actual evaluation of that node. (This policy lets us
* avoid work if the node is never actually evaluated.)
* Any Aggref, WindowFunc, or SubPlan nodes found in the tree are added to the
* lists of such nodes held by the parent PlanState. Otherwise, we do very
* little initialization here other than building the state-node tree. Any
* nontrivial work associated with initializing runtime info for a node should
* happen during the first actual evaluation of that node. (This policy lets
* us avoid work if the node is never actually evaluated.)
*
* Note: there is no ExecEndExpr function; we assume that any resource
* cleanup needed will be handled by just releasing the memory context
@ -4145,11 +4169,49 @@ ExecInitExpr(Expr *node, PlanState *parent)
else
{
/* planner messed up */
elog(ERROR, "aggref found in non-Agg plan node");
elog(ERROR, "Aggref found in non-Agg plan node");
}
state = (ExprState *) astate;
}
break;
case T_WindowFunc:
{
WindowFunc *wfunc = (WindowFunc *) node;
WindowFuncExprState *wfstate = makeNode(WindowFuncExprState);
wfstate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalWindowFunc;
if (parent && IsA(parent, WindowAggState))
{
WindowAggState *winstate = (WindowAggState *) parent;
int nfuncs;
winstate->funcs = lcons(wfstate, winstate->funcs);
nfuncs = ++winstate->numfuncs;
if (wfunc->winagg)
winstate->numaggs++;
wfstate->args = (List *) ExecInitExpr((Expr *) wfunc->args,
parent);
/*
* Complain if the windowfunc's arguments contain any
* windowfuncs; nested window functions are semantically
* nonsensical. (This should have been caught earlier,
* but we defend against it here anyway.)
*/
if (nfuncs != winstate->numfuncs)
ereport(ERROR,
(errcode(ERRCODE_WINDOWING_ERROR),
errmsg("window function calls cannot be nested")));
}
else
{
/* planner messed up */
elog(ERROR, "WindowFunc found in non-WindowAgg plan node");
}
state = (ExprState *) wfstate;
}
break;
case T_ArrayRef:
{
ArrayRef *aref = (ArrayRef *) node;

File diff suppressed because it is too large Load Diff