PostgreSQL Source Code  git master
windowapi.h File Reference
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Macros

#define WINDOW_SEEK_CURRENT   0
 
#define WINDOW_SEEK_HEAD   1
 
#define WINDOW_SEEK_TAIL   2
 
#define PG_WINDOW_OBJECT()   ((WindowObject) fcinfo->context)
 
#define WindowObjectIsValid(winobj)    ((winobj) != NULL && IsA(winobj, WindowObjectData))
 

Typedefs

typedef struct WindowObjectDataWindowObject
 

Functions

void * WinGetPartitionLocalMemory (WindowObject winobj, Size sz)
 
int64 WinGetCurrentPosition (WindowObject winobj)
 
int64 WinGetPartitionRowCount (WindowObject winobj)
 
void WinSetMarkPosition (WindowObject winobj, int64 markpos)
 
bool WinRowsArePeers (WindowObject winobj, int64 pos1, int64 pos2)
 
Datum WinGetFuncArgInPartition (WindowObject winobj, int argno, int relpos, int seektype, bool set_mark, bool *isnull, bool *isout)
 
Datum WinGetFuncArgInFrame (WindowObject winobj, int argno, int relpos, int seektype, bool set_mark, bool *isnull, bool *isout)
 
Datum WinGetFuncArgCurrent (WindowObject winobj, int argno, bool *isnull)
 

Macro Definition Documentation

◆ PG_WINDOW_OBJECT

#define PG_WINDOW_OBJECT ( )    ((WindowObject) fcinfo->context)

Definition at line 39 of file windowapi.h.

◆ WINDOW_SEEK_CURRENT

#define WINDOW_SEEK_CURRENT   0

Definition at line 32 of file windowapi.h.

◆ WINDOW_SEEK_HEAD

#define WINDOW_SEEK_HEAD   1

Definition at line 33 of file windowapi.h.

◆ WINDOW_SEEK_TAIL

#define WINDOW_SEEK_TAIL   2

Definition at line 34 of file windowapi.h.

◆ WindowObjectIsValid

#define WindowObjectIsValid (   winobj)     ((winobj) != NULL && IsA(winobj, WindowObjectData))

Definition at line 41 of file windowapi.h.

Typedef Documentation

◆ WindowObject

typedef struct WindowObjectData* WindowObject

Definition at line 37 of file windowapi.h.

Function Documentation

◆ WinGetCurrentPosition()

int64 WinGetCurrentPosition ( WindowObject  winobj)

Definition at line 3186 of file nodeWindowAgg.c.

3187 {
3188  Assert(WindowObjectIsValid(winobj));
3189  return winobj->winstate->currentpos;
3190 }
#define Assert(condition)
Definition: c.h:858
int64 currentpos
Definition: execnodes.h:2576
WindowAggState * winstate
Definition: nodeWindowAgg.c:65
#define WindowObjectIsValid(winobj)
Definition: windowapi.h:41

References Assert, WindowAggState::currentpos, WindowObjectIsValid, and WindowObjectData::winstate.

Referenced by rank_up(), window_cume_dist(), window_percent_rank(), window_rank(), and window_row_number().

◆ WinGetFuncArgCurrent()

Datum WinGetFuncArgCurrent ( WindowObject  winobj,
int  argno,
bool isnull 
)

Definition at line 3594 of file nodeWindowAgg.c.

3595 {
3596  WindowAggState *winstate;
3597  ExprContext *econtext;
3598 
3599  Assert(WindowObjectIsValid(winobj));
3600  winstate = winobj->winstate;
3601 
3602  econtext = winstate->ss.ps.ps_ExprContext;
3603 
3604  econtext->ecxt_outertuple = winstate->ss.ss_ScanTupleSlot;
3605  return ExecEvalExpr((ExprState *) list_nth(winobj->argstates, argno),
3606  econtext, isnull);
3607 }
static Datum ExecEvalExpr(ExprState *state, ExprContext *econtext, bool *isNull)
Definition: executor.h:333
static void * list_nth(const List *list, int n)
Definition: pg_list.h:299
TupleTableSlot * ecxt_outertuple
Definition: execnodes.h:259
ExprContext * ps_ExprContext
Definition: execnodes.h:1157
TupleTableSlot * ss_ScanTupleSlot
Definition: execnodes.h:1568
PlanState ps
Definition: execnodes.h:1565
ScanState ss
Definition: execnodes.h:2559

References WindowObjectData::argstates, Assert, ExprContext::ecxt_outertuple, ExecEvalExpr(), list_nth(), ScanState::ps, PlanState::ps_ExprContext, WindowAggState::ss, ScanState::ss_ScanTupleSlot, WindowObjectIsValid, and WindowObjectData::winstate.

Referenced by leadlag_common(), window_nth_value(), and window_ntile().

◆ WinGetFuncArgInFrame()

Datum WinGetFuncArgInFrame ( WindowObject  winobj,
int  argno,
int  relpos,
int  seektype,
bool  set_mark,
bool isnull,
bool isout 
)

Definition at line 3399 of file nodeWindowAgg.c.

3402 {
3403  WindowAggState *winstate;
3404  ExprContext *econtext;
3405  TupleTableSlot *slot;
3406  int64 abs_pos;
3407  int64 mark_pos;
3408 
3409  Assert(WindowObjectIsValid(winobj));
3410  winstate = winobj->winstate;
3411  econtext = winstate->ss.ps.ps_ExprContext;
3412  slot = winstate->temp_slot_1;
3413 
3414  switch (seektype)
3415  {
3416  case WINDOW_SEEK_CURRENT:
3417  elog(ERROR, "WINDOW_SEEK_CURRENT is not supported for WinGetFuncArgInFrame");
3418  abs_pos = mark_pos = 0; /* keep compiler quiet */
3419  break;
3420  case WINDOW_SEEK_HEAD:
3421  /* rejecting relpos < 0 is easy and simplifies code below */
3422  if (relpos < 0)
3423  goto out_of_frame;
3424  update_frameheadpos(winstate);
3425  abs_pos = winstate->frameheadpos + relpos;
3426  mark_pos = abs_pos;
3427 
3428  /*
3429  * Account for exclusion option if one is active, but advance only
3430  * abs_pos not mark_pos. This prevents changes of the current
3431  * row's peer group from resulting in trying to fetch a row before
3432  * some previous mark position.
3433  *
3434  * Note that in some corner cases such as current row being
3435  * outside frame, these calculations are theoretically too simple,
3436  * but it doesn't matter because we'll end up deciding the row is
3437  * out of frame. We do not attempt to avoid fetching rows past
3438  * end of frame; that would happen in some cases anyway.
3439  */
3440  switch (winstate->frameOptions & FRAMEOPTION_EXCLUSION)
3441  {
3442  case 0:
3443  /* no adjustment needed */
3444  break;
3446  if (abs_pos >= winstate->currentpos &&
3447  winstate->currentpos >= winstate->frameheadpos)
3448  abs_pos++;
3449  break;
3451  update_grouptailpos(winstate);
3452  if (abs_pos >= winstate->groupheadpos &&
3453  winstate->grouptailpos > winstate->frameheadpos)
3454  {
3455  int64 overlapstart = Max(winstate->groupheadpos,
3456  winstate->frameheadpos);
3457 
3458  abs_pos += winstate->grouptailpos - overlapstart;
3459  }
3460  break;
3462  update_grouptailpos(winstate);
3463  if (abs_pos >= winstate->groupheadpos &&
3464  winstate->grouptailpos > winstate->frameheadpos)
3465  {
3466  int64 overlapstart = Max(winstate->groupheadpos,
3467  winstate->frameheadpos);
3468 
3469  if (abs_pos == overlapstart)
3470  abs_pos = winstate->currentpos;
3471  else
3472  abs_pos += winstate->grouptailpos - overlapstart - 1;
3473  }
3474  break;
3475  default:
3476  elog(ERROR, "unrecognized frame option state: 0x%x",
3477  winstate->frameOptions);
3478  break;
3479  }
3480  break;
3481  case WINDOW_SEEK_TAIL:
3482  /* rejecting relpos > 0 is easy and simplifies code below */
3483  if (relpos > 0)
3484  goto out_of_frame;
3485  update_frametailpos(winstate);
3486  abs_pos = winstate->frametailpos - 1 + relpos;
3487 
3488  /*
3489  * Account for exclusion option if one is active. If there is no
3490  * exclusion, we can safely set the mark at the accessed row. But
3491  * if there is, we can only mark the frame start, because we can't
3492  * be sure how far back in the frame the exclusion might cause us
3493  * to fetch in future. Furthermore, we have to actually check
3494  * against frameheadpos here, since it's unsafe to try to fetch a
3495  * row before frame start if the mark might be there already.
3496  */
3497  switch (winstate->frameOptions & FRAMEOPTION_EXCLUSION)
3498  {
3499  case 0:
3500  /* no adjustment needed */
3501  mark_pos = abs_pos;
3502  break;
3504  if (abs_pos <= winstate->currentpos &&
3505  winstate->currentpos < winstate->frametailpos)
3506  abs_pos--;
3507  update_frameheadpos(winstate);
3508  if (abs_pos < winstate->frameheadpos)
3509  goto out_of_frame;
3510  mark_pos = winstate->frameheadpos;
3511  break;
3513  update_grouptailpos(winstate);
3514  if (abs_pos < winstate->grouptailpos &&
3515  winstate->groupheadpos < winstate->frametailpos)
3516  {
3517  int64 overlapend = Min(winstate->grouptailpos,
3518  winstate->frametailpos);
3519 
3520  abs_pos -= overlapend - winstate->groupheadpos;
3521  }
3522  update_frameheadpos(winstate);
3523  if (abs_pos < winstate->frameheadpos)
3524  goto out_of_frame;
3525  mark_pos = winstate->frameheadpos;
3526  break;
3528  update_grouptailpos(winstate);
3529  if (abs_pos < winstate->grouptailpos &&
3530  winstate->groupheadpos < winstate->frametailpos)
3531  {
3532  int64 overlapend = Min(winstate->grouptailpos,
3533  winstate->frametailpos);
3534 
3535  if (abs_pos == overlapend - 1)
3536  abs_pos = winstate->currentpos;
3537  else
3538  abs_pos -= overlapend - 1 - winstate->groupheadpos;
3539  }
3540  update_frameheadpos(winstate);
3541  if (abs_pos < winstate->frameheadpos)
3542  goto out_of_frame;
3543  mark_pos = winstate->frameheadpos;
3544  break;
3545  default:
3546  elog(ERROR, "unrecognized frame option state: 0x%x",
3547  winstate->frameOptions);
3548  mark_pos = 0; /* keep compiler quiet */
3549  break;
3550  }
3551  break;
3552  default:
3553  elog(ERROR, "unrecognized window seek type: %d", seektype);
3554  abs_pos = mark_pos = 0; /* keep compiler quiet */
3555  break;
3556  }
3557 
3558  if (!window_gettupleslot(winobj, abs_pos, slot))
3559  goto out_of_frame;
3560 
3561  /* The code above does not detect all out-of-frame cases, so check */
3562  if (row_is_in_frame(winstate, abs_pos, slot) <= 0)
3563  goto out_of_frame;
3564 
3565  if (isout)
3566  *isout = false;
3567  if (set_mark)
3568  WinSetMarkPosition(winobj, mark_pos);
3569  econtext->ecxt_outertuple = slot;
3570  return ExecEvalExpr((ExprState *) list_nth(winobj->argstates, argno),
3571  econtext, isnull);
3572 
3573 out_of_frame:
3574  if (isout)
3575  *isout = true;
3576  *isnull = true;
3577  return (Datum) 0;
3578 }
#define Min(x, y)
Definition: c.h:1004
#define Max(x, y)
Definition: c.h:998
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:224
static void update_grouptailpos(WindowAggState *winstate)
static int row_is_in_frame(WindowAggState *winstate, int64 pos, TupleTableSlot *slot)
static bool window_gettupleslot(WindowObject winobj, int64 pos, TupleTableSlot *slot)
void WinSetMarkPosition(WindowObject winobj, int64 markpos)
static void update_frametailpos(WindowAggState *winstate)
static void update_frameheadpos(WindowAggState *winstate)
#define FRAMEOPTION_EXCLUDE_CURRENT_ROW
Definition: parsenodes.h:596
#define FRAMEOPTION_EXCLUDE_TIES
Definition: parsenodes.h:598
#define FRAMEOPTION_EXCLUDE_GROUP
Definition: parsenodes.h:597
#define FRAMEOPTION_EXCLUSION
Definition: parsenodes.h:604
uintptr_t Datum
Definition: postgres.h:64
int64 frameheadpos
Definition: execnodes.h:2577
int64 grouptailpos
Definition: execnodes.h:2603
int64 groupheadpos
Definition: execnodes.h:2602
int64 frametailpos
Definition: execnodes.h:2578
TupleTableSlot * temp_slot_1
Definition: execnodes.h:2639
#define WINDOW_SEEK_TAIL
Definition: windowapi.h:34
#define WINDOW_SEEK_HEAD
Definition: windowapi.h:33
#define WINDOW_SEEK_CURRENT
Definition: windowapi.h:32

References WindowObjectData::argstates, Assert, WindowAggState::currentpos, ExprContext::ecxt_outertuple, elog, ERROR, ExecEvalExpr(), WindowAggState::frameheadpos, FRAMEOPTION_EXCLUDE_CURRENT_ROW, FRAMEOPTION_EXCLUDE_GROUP, FRAMEOPTION_EXCLUDE_TIES, FRAMEOPTION_EXCLUSION, WindowAggState::frameOptions, WindowAggState::frametailpos, WindowAggState::groupheadpos, WindowAggState::grouptailpos, list_nth(), Max, Min, ScanState::ps, PlanState::ps_ExprContext, row_is_in_frame(), WindowAggState::ss, WindowAggState::temp_slot_1, update_frameheadpos(), update_frametailpos(), update_grouptailpos(), window_gettupleslot(), WINDOW_SEEK_CURRENT, WINDOW_SEEK_HEAD, WINDOW_SEEK_TAIL, WindowObjectIsValid, WinSetMarkPosition(), and WindowObjectData::winstate.

Referenced by window_first_value(), window_last_value(), and window_nth_value().

◆ WinGetFuncArgInPartition()

Datum WinGetFuncArgInPartition ( WindowObject  winobj,
int  argno,
int  relpos,
int  seektype,
bool  set_mark,
bool isnull,
bool isout 
)

Definition at line 3311 of file nodeWindowAgg.c.

3314 {
3315  WindowAggState *winstate;
3316  ExprContext *econtext;
3317  TupleTableSlot *slot;
3318  bool gottuple;
3319  int64 abs_pos;
3320 
3321  Assert(WindowObjectIsValid(winobj));
3322  winstate = winobj->winstate;
3323  econtext = winstate->ss.ps.ps_ExprContext;
3324  slot = winstate->temp_slot_1;
3325 
3326  switch (seektype)
3327  {
3328  case WINDOW_SEEK_CURRENT:
3329  abs_pos = winstate->currentpos + relpos;
3330  break;
3331  case WINDOW_SEEK_HEAD:
3332  abs_pos = relpos;
3333  break;
3334  case WINDOW_SEEK_TAIL:
3335  spool_tuples(winstate, -1);
3336  abs_pos = winstate->spooled_rows - 1 + relpos;
3337  break;
3338  default:
3339  elog(ERROR, "unrecognized window seek type: %d", seektype);
3340  abs_pos = 0; /* keep compiler quiet */
3341  break;
3342  }
3343 
3344  gottuple = window_gettupleslot(winobj, abs_pos, slot);
3345 
3346  if (!gottuple)
3347  {
3348  if (isout)
3349  *isout = true;
3350  *isnull = true;
3351  return (Datum) 0;
3352  }
3353  else
3354  {
3355  if (isout)
3356  *isout = false;
3357  if (set_mark)
3358  WinSetMarkPosition(winobj, abs_pos);
3359  econtext->ecxt_outertuple = slot;
3360  return ExecEvalExpr((ExprState *) list_nth(winobj->argstates, argno),
3361  econtext, isnull);
3362  }
3363 }
static void spool_tuples(WindowAggState *winstate, int64 pos)
int64 spooled_rows
Definition: execnodes.h:2575

References WindowObjectData::argstates, Assert, WindowAggState::currentpos, ExprContext::ecxt_outertuple, elog, ERROR, ExecEvalExpr(), list_nth(), ScanState::ps, PlanState::ps_ExprContext, spool_tuples(), WindowAggState::spooled_rows, WindowAggState::ss, WindowAggState::temp_slot_1, window_gettupleslot(), WINDOW_SEEK_CURRENT, WINDOW_SEEK_HEAD, WINDOW_SEEK_TAIL, WindowObjectIsValid, WinSetMarkPosition(), and WindowObjectData::winstate.

Referenced by leadlag_common().

◆ WinGetPartitionLocalMemory()

void* WinGetPartitionLocalMemory ( WindowObject  winobj,
Size  sz 
)

Definition at line 3171 of file nodeWindowAgg.c.

3172 {
3173  Assert(WindowObjectIsValid(winobj));
3174  if (winobj->localmem == NULL)
3175  winobj->localmem =
3177  return winobj->localmem;
3178 }
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:1214
MemoryContext partcontext
Definition: execnodes.h:2605

References Assert, WindowObjectData::localmem, MemoryContextAllocZero(), WindowAggState::partcontext, WindowObjectIsValid, and WindowObjectData::winstate.

Referenced by rank_up(), window_cume_dist(), window_dense_rank(), window_ntile(), window_percent_rank(), and window_rank().

◆ WinGetPartitionRowCount()

int64 WinGetPartitionRowCount ( WindowObject  winobj)

Definition at line 3201 of file nodeWindowAgg.c.

3202 {
3203  Assert(WindowObjectIsValid(winobj));
3204  spool_tuples(winobj->winstate, -1);
3205  return winobj->winstate->spooled_rows;
3206 }

References Assert, spool_tuples(), WindowAggState::spooled_rows, WindowObjectIsValid, and WindowObjectData::winstate.

Referenced by window_cume_dist(), window_ntile(), and window_percent_rank().

◆ WinRowsArePeers()

bool WinRowsArePeers ( WindowObject  winobj,
int64  pos1,
int64  pos2 
)

Definition at line 3254 of file nodeWindowAgg.c.

3255 {
3256  WindowAggState *winstate;
3257  WindowAgg *node;
3258  TupleTableSlot *slot1;
3259  TupleTableSlot *slot2;
3260  bool res;
3261 
3262  Assert(WindowObjectIsValid(winobj));
3263  winstate = winobj->winstate;
3264  node = (WindowAgg *) winstate->ss.ps.plan;
3265 
3266  /* If no ORDER BY, all rows are peers; don't bother to fetch them */
3267  if (node->ordNumCols == 0)
3268  return true;
3269 
3270  /*
3271  * Note: OK to use temp_slot_2 here because we aren't calling any
3272  * frame-related functions (those tend to clobber temp_slot_2).
3273  */
3274  slot1 = winstate->temp_slot_1;
3275  slot2 = winstate->temp_slot_2;
3276 
3277  if (!window_gettupleslot(winobj, pos1, slot1))
3278  elog(ERROR, "specified position is out of window: " INT64_FORMAT,
3279  pos1);
3280  if (!window_gettupleslot(winobj, pos2, slot2))
3281  elog(ERROR, "specified position is out of window: " INT64_FORMAT,
3282  pos2);
3283 
3284  res = are_peers(winstate, slot1, slot2);
3285 
3286  ExecClearTuple(slot1);
3287  ExecClearTuple(slot2);
3288 
3289  return res;
3290 }
#define INT64_FORMAT
Definition: c.h:548
if(TABLE==NULL||TABLE_index==NULL)
Definition: isn.c:77
static bool are_peers(WindowAggState *winstate, TupleTableSlot *slot1, TupleTableSlot *slot2)
Plan * plan
Definition: execnodes.h:1118
TupleTableSlot * temp_slot_2
Definition: execnodes.h:2640
int ordNumCols
Definition: plannodes.h:1058
static TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: tuptable.h:454

References are_peers(), Assert, elog, ERROR, ExecClearTuple(), if(), INT64_FORMAT, WindowAgg::ordNumCols, PlanState::plan, ScanState::ps, res, WindowAggState::ss, WindowAggState::temp_slot_1, WindowAggState::temp_slot_2, window_gettupleslot(), WindowObjectIsValid, and WindowObjectData::winstate.

Referenced by rank_up(), and window_cume_dist().

◆ WinSetMarkPosition()

void WinSetMarkPosition ( WindowObject  winobj,
int64  markpos 
)

Definition at line 3219 of file nodeWindowAgg.c.

3220 {
3221  WindowAggState *winstate;
3222 
3223  Assert(WindowObjectIsValid(winobj));
3224  winstate = winobj->winstate;
3225 
3226  if (markpos < winobj->markpos)
3227  elog(ERROR, "cannot move WindowObject's mark position backward");
3228  tuplestore_select_read_pointer(winstate->buffer, winobj->markptr);
3229  if (markpos > winobj->markpos)
3230  {
3231  tuplestore_skiptuples(winstate->buffer,
3232  markpos - winobj->markpos,
3233  true);
3234  winobj->markpos = markpos;
3235  }
3236  tuplestore_select_read_pointer(winstate->buffer, winobj->readptr);
3237  if (markpos > winobj->seekpos)
3238  {
3239  tuplestore_skiptuples(winstate->buffer,
3240  markpos - winobj->seekpos,
3241  true);
3242  winobj->seekpos = markpos;
3243  }
3244 }
Tuplestorestate * buffer
Definition: execnodes.h:2570
void tuplestore_select_read_pointer(Tuplestorestate *state, int ptr)
Definition: tuplestore.c:473
bool tuplestore_skiptuples(Tuplestorestate *state, int64 ntuples, bool forward)
Definition: tuplestore.c:1135

References Assert, WindowAggState::buffer, elog, ERROR, WindowObjectData::markpos, WindowObjectData::markptr, WindowObjectData::readptr, WindowObjectData::seekpos, tuplestore_select_read_pointer(), tuplestore_skiptuples(), WindowObjectIsValid, and WindowObjectData::winstate.

Referenced by eval_windowaggregates(), rank_up(), window_row_number(), WinGetFuncArgInFrame(), and WinGetFuncArgInPartition().