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:
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
1854
src/backend/executor/nodeWindowAgg.c
Normal file
1854
src/backend/executor/nodeWindowAgg.c
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user