PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
nodeWindowAgg.h File Reference
#include "nodes/execnodes.h"
Include dependency graph for nodeWindowAgg.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

WindowAggStateExecInitWindowAgg (WindowAgg *node, EState *estate, int eflags)
 
TupleTableSlotExecWindowAgg (WindowAggState *node)
 
void ExecEndWindowAgg (WindowAggState *node)
 
void ExecReScanWindowAgg (WindowAggState *node)
 

Function Documentation

void ExecEndWindowAgg ( WindowAggState node)

Definition at line 2013 of file nodeWindowAgg.c.

References WindowAggState::agg_row_slot, WindowStatePerAggData::aggcontext, WindowAggState::aggcontext, ExecClearTuple(), ExecEndNode(), ExecFreeExprContext(), WindowAggState::first_part_slot, i, MemoryContextDelete(), WindowAggState::numaggs, outerPlan, outerPlanState, WindowAggState::partcontext, WindowAggState::peragg, WindowAggState::perfunc, pfree(), ScanState::ps, PlanState::ps_ExprContext, release_partition(), WindowAggState::ss, ScanState::ss_ScanTupleSlot, WindowAggState::temp_slot_1, WindowAggState::temp_slot_2, and WindowAggState::tmpcontext.

Referenced by ExecEndNode().

2014 {
2016  int i;
2017 
2018  release_partition(node);
2019 
2023  ExecClearTuple(node->temp_slot_1);
2024  ExecClearTuple(node->temp_slot_2);
2025 
2026  /*
2027  * Free both the expr contexts.
2028  */
2029  ExecFreeExprContext(&node->ss.ps);
2030  node->ss.ps.ps_ExprContext = node->tmpcontext;
2031  ExecFreeExprContext(&node->ss.ps);
2032 
2033  for (i = 0; i < node->numaggs; i++)
2034  {
2035  if (node->peragg[i].aggcontext != node->aggcontext)
2037  }
2040 
2041  pfree(node->perfunc);
2042  pfree(node->peragg);
2043 
2044  outerPlan = outerPlanState(node);
2045  ExecEndNode(outerPlan);
2046 }
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:200
ScanState ss
Definition: execnodes.h:2004
void ExecEndNode(PlanState *node)
Definition: execProcnode.c:644
ExprContext * ps_ExprContext
Definition: execnodes.h:1080
TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: execTuples.c:439
TupleTableSlot * ss_ScanTupleSlot
Definition: execnodes.h:1293
static void release_partition(WindowAggState *winstate)
TupleTableSlot * temp_slot_1
Definition: execnodes.h:2055
WindowStatePerFunc perfunc
Definition: execnodes.h:2011
void ExecFreeExprContext(PlanState *planstate)
Definition: execUtils.c:686
TupleTableSlot * first_part_slot
Definition: execnodes.h:2050
ExprContext * tmpcontext
Definition: execnodes.h:2036
PlanState ps
Definition: execnodes.h:1290
void pfree(void *pointer)
Definition: mcxt.c:950
#define outerPlanState(node)
Definition: execnodes.h:1092
TupleTableSlot * temp_slot_2
Definition: execnodes.h:2056
WindowStatePerAgg peragg
Definition: execnodes.h:2012
MemoryContext aggcontext
Definition: execnodes.h:2034
#define outerPlan(node)
Definition: plannodes.h:162
TupleTableSlot * agg_row_slot
Definition: execnodes.h:2054
MemoryContext aggcontext
int i
MemoryContext partcontext
Definition: execnodes.h:2033
WindowAggState* ExecInitWindowAgg ( WindowAgg node,
EState estate,
int  eflags 
)

Definition at line 1768 of file nodeWindowAgg.c.

References ACL_EXECUTE, ACL_KIND_PROC, aclcheck_error(), ACLCHECK_OK, WindowAggState::agg_row_slot, WindowAggState::agg_winobj, WindowAggState::aggcontext, WindowAggState::all_first, ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate(), WindowFuncExprState::args, WindowObjectData::argstates, Assert, contain_volatile_functions(), CurrentMemoryContext, ExprContext::ecxt_aggnulls, ExprContext::ecxt_aggvalues, ExprContext::ecxt_per_query_memory, elog, WindowAgg::endOffset, WindowAggState::endOffset, equal(), ERROR, EXEC_FLAG_BACKWARD, EXEC_FLAG_MARK, ExecAssignExprContext(), ExecAssignProjectionInfo(), ExecAssignResultTypeFromTL(), ExecAssignScanTypeFromOuterPlan(), ExecInitExpr(), ExecInitExtraTupleSlot(), ExecInitNode(), ExecInitResultTupleSlot(), ExecInitScanTupleSlot(), ExecSetSlotDescriptor(), execTuplesMatchPrepare(), ExprState::expr, WindowAggState::first_part_slot, fmgr_info_cxt(), fmgr_info_set_expr, WindowAgg::frameOptions, WindowAggState::frameOptions, WindowAggState::funcs, get_func_name(), get_typlenbyval(), GetUserId(), i, initialize_peragg(), WindowFunc::inputcollid, InvokeFunctionExecuteHook, lfirst, list_length(), WindowObjectData::localmem, makeNode, WindowObjectData::markptr, WindowAggState::more_partitions, NIL, NULL, WindowAggState::numaggs, WindowAggState::numfuncs, WindowAggState::ordEqfunctions, WindowAgg::ordNumCols, WindowAgg::ordOperators, outerPlan, outerPlanState, palloc0(), WindowAggState::partcontext, WindowAggState::partEqfunctions, WindowAggState::partition_spooled, WindowAgg::partNumCols, WindowAgg::partOperators, WindowAggState::peragg, WindowAggState::perfunc, pg_proc_aclcheck(), WindowAgg::plan, PlanState::plan, ScanState::ps, PlanState::ps_ExprContext, Plan::qual, PlanState::qual, WindowObjectData::readptr, WindowAggState::ss, ScanState::ss_ScanTupleSlot, WindowAgg::startOffset, WindowAggState::startOffset, PlanState::state, Plan::targetlist, PlanState::targetlist, WindowAggState::temp_slot_1, WindowAggState::temp_slot_2, WindowAggState::tmpcontext, TupleTableSlot::tts_tupleDescriptor, WindowStatePerAggData::wfuncno, WindowFuncExprState::wfuncno, WindowFunc::winagg, WindowFunc::winfnoid, WindowFunc::winref, WindowAgg::winref, WindowObjectData::winstate, WindowFunc::wintype, and WindowFuncExprState::xprstate.

Referenced by ExecInitNode().

1769 {
1770  WindowAggState *winstate;
1771  Plan *outerPlan;
1772  ExprContext *econtext;
1773  ExprContext *tmpcontext;
1774  WindowStatePerFunc perfunc;
1775  WindowStatePerAgg peragg;
1776  int numfuncs,
1777  wfuncno,
1778  numaggs,
1779  aggno;
1780  ListCell *l;
1781 
1782  /* check for unsupported flags */
1783  Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)));
1784 
1785  /*
1786  * create state structure
1787  */
1788  winstate = makeNode(WindowAggState);
1789  winstate->ss.ps.plan = (Plan *) node;
1790  winstate->ss.ps.state = estate;
1791 
1792  /*
1793  * Create expression contexts. We need two, one for per-input-tuple
1794  * processing and one for per-output-tuple processing. We cheat a little
1795  * by using ExecAssignExprContext() to build both.
1796  */
1797  ExecAssignExprContext(estate, &winstate->ss.ps);
1798  tmpcontext = winstate->ss.ps.ps_ExprContext;
1799  winstate->tmpcontext = tmpcontext;
1800  ExecAssignExprContext(estate, &winstate->ss.ps);
1801 
1802  /* Create long-lived context for storage of partition-local memory etc */
1803  winstate->partcontext =
1805  "WindowAgg Partition",
1807 
1808  /*
1809  * Create mid-lived context for aggregate trans values etc.
1810  *
1811  * Note that moving aggregates each use their own private context, not
1812  * this one.
1813  */
1814  winstate->aggcontext =
1816  "WindowAgg Aggregates",
1818 
1819  /*
1820  * tuple table initialization
1821  */
1822  ExecInitScanTupleSlot(estate, &winstate->ss);
1823  ExecInitResultTupleSlot(estate, &winstate->ss.ps);
1824  winstate->first_part_slot = ExecInitExtraTupleSlot(estate);
1825  winstate->agg_row_slot = ExecInitExtraTupleSlot(estate);
1826  winstate->temp_slot_1 = ExecInitExtraTupleSlot(estate);
1827  winstate->temp_slot_2 = ExecInitExtraTupleSlot(estate);
1828 
1829  winstate->ss.ps.targetlist = (List *)
1830  ExecInitExpr((Expr *) node->plan.targetlist,
1831  (PlanState *) winstate);
1832 
1833  /*
1834  * WindowAgg nodes never have quals, since they can only occur at the
1835  * logical top level of a query (ie, after any WHERE or HAVING filters)
1836  */
1837  Assert(node->plan.qual == NIL);
1838  winstate->ss.ps.qual = NIL;
1839 
1840  /*
1841  * initialize child nodes
1842  */
1843  outerPlan = outerPlan(node);
1844  outerPlanState(winstate) = ExecInitNode(outerPlan, estate, eflags);
1845 
1846  /*
1847  * initialize source tuple type (which is also the tuple type that we'll
1848  * store in the tuplestore and use in all our working slots).
1849  */
1850  ExecAssignScanTypeFromOuterPlan(&winstate->ss);
1851 
1860 
1861  /*
1862  * Initialize result tuple type and projection info.
1863  */
1864  ExecAssignResultTypeFromTL(&winstate->ss.ps);
1865  ExecAssignProjectionInfo(&winstate->ss.ps, NULL);
1866 
1867  /* Set up data for comparing tuples */
1868  if (node->partNumCols > 0)
1870  node->partOperators);
1871  if (node->ordNumCols > 0)
1873  node->ordOperators);
1874 
1875  /*
1876  * WindowAgg nodes use aggvalues and aggnulls as well as Agg nodes.
1877  */
1878  numfuncs = winstate->numfuncs;
1879  numaggs = winstate->numaggs;
1880  econtext = winstate->ss.ps.ps_ExprContext;
1881  econtext->ecxt_aggvalues = (Datum *) palloc0(sizeof(Datum) * numfuncs);
1882  econtext->ecxt_aggnulls = (bool *) palloc0(sizeof(bool) * numfuncs);
1883 
1884  /*
1885  * allocate per-wfunc/per-agg state information.
1886  */
1887  perfunc = (WindowStatePerFunc) palloc0(sizeof(WindowStatePerFuncData) * numfuncs);
1888  peragg = (WindowStatePerAgg) palloc0(sizeof(WindowStatePerAggData) * numaggs);
1889  winstate->perfunc = perfunc;
1890  winstate->peragg = peragg;
1891 
1892  wfuncno = -1;
1893  aggno = -1;
1894  foreach(l, winstate->funcs)
1895  {
1896  WindowFuncExprState *wfuncstate = (WindowFuncExprState *) lfirst(l);
1897  WindowFunc *wfunc = (WindowFunc *) wfuncstate->xprstate.expr;
1898  WindowStatePerFunc perfuncstate;
1899  AclResult aclresult;
1900  int i;
1901 
1902  if (wfunc->winref != node->winref) /* planner screwed up? */
1903  elog(ERROR, "WindowFunc with winref %u assigned to WindowAgg with winref %u",
1904  wfunc->winref, node->winref);
1905 
1906  /* Look for a previous duplicate window function */
1907  for (i = 0; i <= wfuncno; i++)
1908  {
1909  if (equal(wfunc, perfunc[i].wfunc) &&
1910  !contain_volatile_functions((Node *) wfunc))
1911  break;
1912  }
1913  if (i <= wfuncno)
1914  {
1915  /* Found a match to an existing entry, so just mark it */
1916  wfuncstate->wfuncno = i;
1917  continue;
1918  }
1919 
1920  /* Nope, so assign a new PerAgg record */
1921  perfuncstate = &perfunc[++wfuncno];
1922 
1923  /* Mark WindowFunc state node with assigned index in the result array */
1924  wfuncstate->wfuncno = wfuncno;
1925 
1926  /* Check permission to call window function */
1927  aclresult = pg_proc_aclcheck(wfunc->winfnoid, GetUserId(),
1928  ACL_EXECUTE);
1929  if (aclresult != ACLCHECK_OK)
1930  aclcheck_error(aclresult, ACL_KIND_PROC,
1931  get_func_name(wfunc->winfnoid));
1932  InvokeFunctionExecuteHook(wfunc->winfnoid);
1933 
1934  /* Fill in the perfuncstate data */
1935  perfuncstate->wfuncstate = wfuncstate;
1936  perfuncstate->wfunc = wfunc;
1937  perfuncstate->numArguments = list_length(wfuncstate->args);
1938 
1939  fmgr_info_cxt(wfunc->winfnoid, &perfuncstate->flinfo,
1940  econtext->ecxt_per_query_memory);
1941  fmgr_info_set_expr((Node *) wfunc, &perfuncstate->flinfo);
1942 
1943  perfuncstate->winCollation = wfunc->inputcollid;
1944 
1945  get_typlenbyval(wfunc->wintype,
1946  &perfuncstate->resulttypeLen,
1947  &perfuncstate->resulttypeByVal);
1948 
1949  /*
1950  * If it's really just a plain aggregate function, we'll emulate the
1951  * Agg environment for it.
1952  */
1953  perfuncstate->plain_agg = wfunc->winagg;
1954  if (wfunc->winagg)
1955  {
1956  WindowStatePerAgg peraggstate;
1957 
1958  perfuncstate->aggno = ++aggno;
1959  peraggstate = &winstate->peragg[aggno];
1960  initialize_peragg(winstate, wfunc, peraggstate);
1961  peraggstate->wfuncno = wfuncno;
1962  }
1963  else
1964  {
1966 
1967  winobj->winstate = winstate;
1968  winobj->argstates = wfuncstate->args;
1969  winobj->localmem = NULL;
1970  perfuncstate->winobj = winobj;
1971  }
1972  }
1973 
1974  /* Update numfuncs, numaggs to match number of unique functions found */
1975  winstate->numfuncs = wfuncno + 1;
1976  winstate->numaggs = aggno + 1;
1977 
1978  /* Set up WindowObject for aggregates, if needed */
1979  if (winstate->numaggs > 0)
1980  {
1981  WindowObject agg_winobj = makeNode(WindowObjectData);
1982 
1983  agg_winobj->winstate = winstate;
1984  agg_winobj->argstates = NIL;
1985  agg_winobj->localmem = NULL;
1986  /* make sure markptr = -1 to invalidate. It may not get used */
1987  agg_winobj->markptr = -1;
1988  agg_winobj->readptr = -1;
1989  winstate->agg_winobj = agg_winobj;
1990  }
1991 
1992  /* copy frame options to state node for easy access */
1993  winstate->frameOptions = node->frameOptions;
1994 
1995  /* initialize frame bound offset expressions */
1996  winstate->startOffset = ExecInitExpr((Expr *) node->startOffset,
1997  (PlanState *) winstate);
1998  winstate->endOffset = ExecInitExpr((Expr *) node->endOffset,
1999  (PlanState *) winstate);
2000 
2001  winstate->all_first = true;
2002  winstate->partition_spooled = false;
2003  winstate->more_partitions = false;
2004 
2005  return winstate;
2006 }
int ordNumCols
Definition: plannodes.h:777
#define NIL
Definition: pg_list.h:69
List * qual
Definition: plannodes.h:133
ExprState * endOffset
Definition: execnodes.h:2029
TupleTableSlot * ExecInitExtraTupleSlot(EState *estate)
Definition: execTuples.c:852
Datum * ecxt_aggvalues
Definition: execnodes.h:146
struct WindowStatePerAggData * WindowStatePerAgg
Definition: execnodes.h:2000
void ExecInitScanTupleSlot(EState *estate, ScanState *scanstate)
Definition: execTuples.c:842
bool equal(const void *a, const void *b)
Definition: equalfuncs.c:2926
Oid GetUserId(void)
Definition: miscinit.c:283
ScanState ss
Definition: execnodes.h:2004
ExprContext * ps_ExprContext
Definition: execnodes.h:1080
ExprState xprstate
Definition: execnodes.h:661
List * qual
Definition: execnodes.h:1064
Definition: nodes.h:519
List * targetlist
Definition: execnodes.h:1063
TupleTableSlot * ss_ScanTupleSlot
Definition: execnodes.h:1293
struct WindowStatePerFuncData * WindowStatePerFunc
Definition: execnodes.h:1999
FmgrInfo * partEqfunctions
Definition: execnodes.h:2013
bool contain_volatile_functions(Node *clause)
Definition: clauses.c:950
EState * state
Definition: execnodes.h:1051
Index winref
Definition: primnodes.h:361
TupleTableSlot * temp_slot_1
Definition: execnodes.h:2055
WindowStatePerFunc perfunc
Definition: execnodes.h:2011
Oid * ordOperators
Definition: plannodes.h:779
void ExecAssignResultTypeFromTL(PlanState *planstate)
Definition: execUtils.c:431
TupleTableSlot * first_part_slot
Definition: execnodes.h:2050
ExprContext * tmpcontext
Definition: execnodes.h:2036
PlanState ps
Definition: execnodes.h:1290
struct WindowObjectData * agg_winobj
Definition: execnodes.h:2022
Node * startOffset
Definition: plannodes.h:781
static WindowStatePerAggData * initialize_peragg(WindowAggState *winstate, WindowFunc *wfunc, WindowStatePerAgg peraggstate)
ExprState * ExecInitExpr(Expr *node, PlanState *parent)
Definition: execQual.c:4267
#define ERROR
Definition: elog.h:43
Expr * expr
Definition: execnodes.h:600
char * get_func_name(Oid funcid)
Definition: lsyscache.c:1380
void ExecInitResultTupleSlot(EState *estate, PlanState *planstate)
Definition: execTuples.c:832
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:165
#define EXEC_FLAG_BACKWARD
Definition: executor.h:60
#define outerPlanState(node)
Definition: execnodes.h:1092
TupleTableSlot * temp_slot_2
Definition: execnodes.h:2056
WindowStatePerAgg peragg
Definition: execnodes.h:2012
ExprState * startOffset
Definition: execnodes.h:2028
void ExecAssignProjectionInfo(PlanState *planstate, TupleDesc inputDesc)
Definition: execUtils.c:658
void aclcheck_error(AclResult aclerr, AclObjectKind objectkind, const char *objectname)
Definition: aclchk.c:3377
Node * endOffset
Definition: plannodes.h:782
#define fmgr_info_set_expr(expr, finfo)
Definition: fmgr.h:96
int partNumCols
Definition: plannodes.h:774
MemoryContext CurrentMemoryContext
Definition: mcxt.c:37
MemoryContext aggcontext
Definition: execnodes.h:2034
void fmgr_info_cxt(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt)
Definition: fmgr.c:169
#define InvokeFunctionExecuteHook(objectId)
Definition: objectaccess.h:179
#define outerPlan(node)
Definition: plannodes.h:162
TupleDesc tts_tupleDescriptor
Definition: tuptable.h:121
bool * ecxt_aggnulls
Definition: execnodes.h:147
WindowAggState * winstate
Definition: nodeWindowAgg.c:62
MemoryContext AllocSetContextCreate(MemoryContext parent, const char *name, Size minContextSize, Size initBlockSize, Size maxBlockSize)
Definition: aset.c:322
void * palloc0(Size size)
Definition: mcxt.c:878
AclResult
Definition: acl.h:170
uintptr_t Datum
Definition: postgres.h:372
void ExecSetSlotDescriptor(TupleTableSlot *slot, TupleDesc tupdesc)
Definition: execTuples.c:247
TupleTableSlot * agg_row_slot
Definition: execnodes.h:2054
Plan * plan
Definition: execnodes.h:1049
bool more_partitions
Definition: execnodes.h:2043
FmgrInfo * ordEqfunctions
Definition: execnodes.h:2014
Oid * partOperators
Definition: plannodes.h:776
#define makeNode(_type_)
Definition: nodes.h:567
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
#define lfirst(lc)
Definition: pg_list.h:106
Index winref
Definition: plannodes.h:773
#define EXEC_FLAG_MARK
Definition: executor.h:61
void ExecAssignExprContext(EState *estate, PlanState *planstate)
Definition: execUtils.c:409
static int list_length(const List *l)
Definition: pg_list.h:89
void get_typlenbyval(Oid typid, int16 *typlen, bool *typbyval)
Definition: lsyscache.c:1969
MemoryContext ecxt_per_query_memory
Definition: execnodes.h:135
List * targetlist
Definition: plannodes.h:132
bool partition_spooled
Definition: execnodes.h:2040
void ExecAssignScanTypeFromOuterPlan(ScanState *scanstate)
Definition: execUtils.c:722
#define ACL_EXECUTE
Definition: parsenodes.h:72
AclResult pg_proc_aclcheck(Oid proc_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4420
int i
Plan plan
Definition: plannodes.h:772
MemoryContext partcontext
Definition: execnodes.h:2033
#define elog
Definition: elog.h:219
int frameOptions
Definition: plannodes.h:780
FmgrInfo * execTuplesMatchPrepare(int numCols, Oid *eqOperators)
Definition: execGrouping.c:204
PlanState * ExecInitNode(Plan *node, EState *estate, int eflags)
Definition: execProcnode.c:139
Definition: pg_list.h:45
void ExecReScanWindowAgg ( WindowAggState node)

Definition at line 2053 of file nodeWindowAgg.c.

References WindowAggState::agg_row_slot, WindowAggState::all_done, WindowAggState::all_first, PlanState::chgParam, ExprContext::ecxt_aggnulls, ExprContext::ecxt_aggvalues, ExecClearTuple(), ExecReScan(), WindowAggState::first_part_slot, MemSet, NULL, WindowAggState::numfuncs, outerPlan, outerPlanState, ScanState::ps, PlanState::ps_ExprContext, release_partition(), WindowAggState::ss, ScanState::ss_ScanTupleSlot, WindowAggState::temp_slot_1, and WindowAggState::temp_slot_2.

Referenced by ExecReScan().

2054 {
2056  ExprContext *econtext = node->ss.ps.ps_ExprContext;
2057 
2058  node->all_done = false;
2059  node->all_first = true;
2060 
2061  /* release tuplestore et al */
2062  release_partition(node);
2063 
2064  /* release all temp tuples, but especially first_part_slot */
2068  ExecClearTuple(node->temp_slot_1);
2069  ExecClearTuple(node->temp_slot_2);
2070 
2071  /* Forget current wfunc values */
2072  MemSet(econtext->ecxt_aggvalues, 0, sizeof(Datum) * node->numfuncs);
2073  MemSet(econtext->ecxt_aggnulls, 0, sizeof(bool) * node->numfuncs);
2074 
2075  /*
2076  * if chgParam of subnode is not null then plan will be re-scanned by
2077  * first ExecProcNode.
2078  */
2079  if (outerPlan->chgParam == NULL)
2080  ExecReScan(outerPlan);
2081 }
Datum * ecxt_aggvalues
Definition: execnodes.h:146
ScanState ss
Definition: execnodes.h:2004
ExprContext * ps_ExprContext
Definition: execnodes.h:1080
void ExecReScan(PlanState *node)
Definition: execAmi.c:74
TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: execTuples.c:439
#define MemSet(start, val, len)
Definition: c.h:857
TupleTableSlot * ss_ScanTupleSlot
Definition: execnodes.h:1293
static void release_partition(WindowAggState *winstate)
TupleTableSlot * temp_slot_1
Definition: execnodes.h:2055
TupleTableSlot * first_part_slot
Definition: execnodes.h:2050
PlanState ps
Definition: execnodes.h:1290
#define outerPlanState(node)
Definition: execnodes.h:1092
TupleTableSlot * temp_slot_2
Definition: execnodes.h:2056
Bitmapset * chgParam
Definition: execnodes.h:1074
#define outerPlan(node)
Definition: plannodes.h:162
bool * ecxt_aggnulls
Definition: execnodes.h:147
uintptr_t Datum
Definition: postgres.h:372
TupleTableSlot * agg_row_slot
Definition: execnodes.h:2054
#define NULL
Definition: c.h:229
TupleTableSlot* ExecWindowAgg ( WindowAggState node)

Definition at line 1591 of file nodeWindowAgg.c.

References WindowAggState::all_done, WindowAggState::all_first, Assert, begin_partition(), WindowAggState::buffer, WindowAggState::current_ptr, WindowAggState::currentpos, datumCopy(), DatumGetInt64, ExprContext::ecxt_aggnulls, ExprContext::ecxt_aggvalues, ExprContext::ecxt_outertuple, elog, WindowAggState::endOffset, WindowAggState::endOffsetValue, ereport, errcode(), errmsg(), ERROR, eval_windowaggregates(), eval_windowfunction(), ExecEvalExprSwitchContext(), ExecProject(), ExprState::expr, exprType(), WindowAggState::framehead_valid, FRAMEOPTION_END_VALUE, FRAMEOPTION_ROWS, FRAMEOPTION_START_VALUE, WindowAggState::frameOptions, WindowAggState::frametail_valid, get_typlenbyval(), i, WindowAggState::more_partitions, NULL, WindowAggState::numaggs, WindowAggState::numfuncs, WindowAggState::partition_spooled, WindowAggState::perfunc, WindowStatePerFuncData::plain_agg, ScanState::ps, PlanState::ps_ExprContext, PlanState::ps_ProjInfo, release_partition(), ResetExprContext, spool_tuples(), WindowAggState::spooled_rows, WindowAggState::ss, ScanState::ss_ScanTupleSlot, WindowAggState::startOffset, WindowAggState::startOffsetValue, tuplestore_gettupleslot(), tuplestore_select_read_pointer(), tuplestore_trim(), value, WindowFuncExprState::wfuncno, and WindowStatePerFuncData::wfuncstate.

Referenced by ExecProcNode().

1592 {
1593  ExprContext *econtext;
1594  int i;
1595  int numfuncs;
1596 
1597  if (winstate->all_done)
1598  return NULL;
1599 
1600  /*
1601  * Compute frame offset values, if any, during first call.
1602  */
1603  if (winstate->all_first)
1604  {
1605  int frameOptions = winstate->frameOptions;
1606  ExprContext *econtext = winstate->ss.ps.ps_ExprContext;
1607  Datum value;
1608  bool isnull;
1609  int16 len;
1610  bool byval;
1611 
1612  if (frameOptions & FRAMEOPTION_START_VALUE)
1613  {
1614  Assert(winstate->startOffset != NULL);
1615  value = ExecEvalExprSwitchContext(winstate->startOffset,
1616  econtext,
1617  &isnull);
1618  if (isnull)
1619  ereport(ERROR,
1620  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
1621  errmsg("frame starting offset must not be null")));
1622  /* copy value into query-lifespan context */
1623  get_typlenbyval(exprType((Node *) winstate->startOffset->expr),
1624  &len, &byval);
1625  winstate->startOffsetValue = datumCopy(value, byval, len);
1626  if (frameOptions & FRAMEOPTION_ROWS)
1627  {
1628  /* value is known to be int8 */
1629  int64 offset = DatumGetInt64(value);
1630 
1631  if (offset < 0)
1632  ereport(ERROR,
1633  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1634  errmsg("frame starting offset must not be negative")));
1635  }
1636  }
1637  if (frameOptions & FRAMEOPTION_END_VALUE)
1638  {
1639  Assert(winstate->endOffset != NULL);
1640  value = ExecEvalExprSwitchContext(winstate->endOffset,
1641  econtext,
1642  &isnull);
1643  if (isnull)
1644  ereport(ERROR,
1645  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
1646  errmsg("frame ending offset must not be null")));
1647  /* copy value into query-lifespan context */
1648  get_typlenbyval(exprType((Node *) winstate->endOffset->expr),
1649  &len, &byval);
1650  winstate->endOffsetValue = datumCopy(value, byval, len);
1651  if (frameOptions & FRAMEOPTION_ROWS)
1652  {
1653  /* value is known to be int8 */
1654  int64 offset = DatumGetInt64(value);
1655 
1656  if (offset < 0)
1657  ereport(ERROR,
1658  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1659  errmsg("frame ending offset must not be negative")));
1660  }
1661  }
1662  winstate->all_first = false;
1663  }
1664 
1665  if (winstate->buffer == NULL)
1666  {
1667  /* Initialize for first partition and set current row = 0 */
1668  begin_partition(winstate);
1669  /* If there are no input rows, we'll detect that and exit below */
1670  }
1671  else
1672  {
1673  /* Advance current row within partition */
1674  winstate->currentpos++;
1675  /* This might mean that the frame moves, too */
1676  winstate->framehead_valid = false;
1677  winstate->frametail_valid = false;
1678  }
1679 
1680  /*
1681  * Spool all tuples up to and including the current row, if we haven't
1682  * already
1683  */
1684  spool_tuples(winstate, winstate->currentpos);
1685 
1686  /* Move to the next partition if we reached the end of this partition */
1687  if (winstate->partition_spooled &&
1688  winstate->currentpos >= winstate->spooled_rows)
1689  {
1690  release_partition(winstate);
1691 
1692  if (winstate->more_partitions)
1693  {
1694  begin_partition(winstate);
1695  Assert(winstate->spooled_rows > 0);
1696  }
1697  else
1698  {
1699  winstate->all_done = true;
1700  return NULL;
1701  }
1702  }
1703 
1704  /* final output execution is in ps_ExprContext */
1705  econtext = winstate->ss.ps.ps_ExprContext;
1706 
1707  /* Clear the per-output-tuple context for current row */
1708  ResetExprContext(econtext);
1709 
1710  /*
1711  * Read the current row from the tuplestore, and save in ScanTupleSlot.
1712  * (We can't rely on the outerplan's output slot because we may have to
1713  * read beyond the current row. Also, we have to actually copy the row
1714  * out of the tuplestore, since window function evaluation might cause the
1715  * tuplestore to dump its state to disk.)
1716  *
1717  * Current row must be in the tuplestore, since we spooled it above.
1718  */
1719  tuplestore_select_read_pointer(winstate->buffer, winstate->current_ptr);
1720  if (!tuplestore_gettupleslot(winstate->buffer, true, true,
1721  winstate->ss.ss_ScanTupleSlot))
1722  elog(ERROR, "unexpected end of tuplestore");
1723 
1724  /*
1725  * Evaluate true window functions
1726  */
1727  numfuncs = winstate->numfuncs;
1728  for (i = 0; i < numfuncs; i++)
1729  {
1730  WindowStatePerFunc perfuncstate = &(winstate->perfunc[i]);
1731 
1732  if (perfuncstate->plain_agg)
1733  continue;
1734  eval_windowfunction(winstate, perfuncstate,
1735  &(econtext->ecxt_aggvalues[perfuncstate->wfuncstate->wfuncno]),
1736  &(econtext->ecxt_aggnulls[perfuncstate->wfuncstate->wfuncno]));
1737  }
1738 
1739  /*
1740  * Evaluate aggregates
1741  */
1742  if (winstate->numaggs > 0)
1743  eval_windowaggregates(winstate);
1744 
1745  /*
1746  * Truncate any no-longer-needed rows from the tuplestore.
1747  */
1748  tuplestore_trim(winstate->buffer);
1749 
1750  /*
1751  * Form and return a projection tuple using the windowfunc results and the
1752  * current row. Setting ecxt_outertuple arranges that any Vars will be
1753  * evaluated with respect to that row.
1754  */
1755  econtext->ecxt_outertuple = winstate->ss.ss_ScanTupleSlot;
1756 
1757  return ExecProject(winstate->ss.ps.ps_ProjInfo);
1758 }
static struct @77 value
signed short int16
Definition: c.h:255
TupleTableSlot * ExecProject(ProjectionInfo *projInfo)
Definition: execQual.c:5215
Datum * ecxt_aggvalues
Definition: execnodes.h:146
void tuplestore_trim(Tuplestorestate *state)
Definition: tuplestore.c:1343
#define FRAMEOPTION_START_VALUE
Definition: parsenodes.h:511
Definition: nodes.h:519
int errcode(int sqlerrcode)
Definition: elog.c:575
static void release_partition(WindowAggState *winstate)
WindowFuncExprState * wfuncstate
Definition: nodeWindowAgg.c:78
Datum ExecEvalExprSwitchContext(ExprState *expression, ExprContext *econtext, bool *isNull)
Definition: execQual.c:4220
static void spool_tuples(WindowAggState *winstate, int64 pos)
#define ERROR
Definition: elog.h:43
#define DatumGetInt64(X)
Definition: postgres.h:613
#define ereport(elevel, rest)
Definition: elog.h:122
Datum datumCopy(Datum value, bool typByVal, int typLen)
Definition: datum.c:128
static void eval_windowaggregates(WindowAggState *winstate)
bool * ecxt_aggnulls
Definition: execnodes.h:147
uintptr_t Datum
Definition: postgres.h:372
static void begin_partition(WindowAggState *winstate)
bool tuplestore_gettupleslot(Tuplestorestate *state, bool forward, bool copy, TupleTableSlot *slot)
Definition: tuplestore.c:1061
TupleTableSlot * ecxt_outertuple
Definition: execnodes.h:132
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:42
void get_typlenbyval(Oid typid, int16 *typlen, bool *typbyval)
Definition: lsyscache.c:1969
#define FRAMEOPTION_ROWS
Definition: parsenodes.h:498
int errmsg(const char *fmt,...)
Definition: elog.c:797
int i
void tuplestore_select_read_pointer(Tuplestorestate *state, int ptr)
Definition: tuplestore.c:470
#define elog
Definition: elog.h:219
#define FRAMEOPTION_END_VALUE
Definition: parsenodes.h:513
static void eval_windowfunction(WindowAggState *winstate, WindowStatePerFunc perfuncstate, Datum *result, bool *isnull)
#define ResetExprContext(econtext)
Definition: executor.h:333