* WinGetFuncArgInFrame * Evaluate a window function's argument expression on a specified * row of the window frame. The row is identified in lseek(2) style, * i.e. relative to the first or last row of the frame. (We do not * support WINDOW_SEEK_CURRENT here, because it's not very clear what * that should mean if the current row isn't part of the frame.) * * argno: argument number to
| 3672 | * about relpos. |
| 3673 | */ |
| 3674 | Datum |
| 3675 | WinGetFuncArgInFrame(WindowObject winobj, int argno, |
| 3676 | int relpos, int seektype, bool set_mark, |
| 3677 | bool *isnull, bool *isout) |
| 3678 | { |
| 3679 | WindowAggState *winstate; |
| 3680 | ExprContext *econtext; |
| 3681 | TupleTableSlot *slot; |
| 3682 | int64 abs_pos; |
| 3683 | int64 mark_pos; |
| 3684 | |
| 3685 | Assert(WindowObjectIsValid(winobj)); |
| 3686 | winstate = winobj->winstate; |
| 3687 | econtext = winstate->ss.ps.ps_ExprContext; |
| 3688 | slot = winstate->temp_slot_1; |
| 3689 | |
| 3690 | switch (seektype) |
| 3691 | { |
| 3692 | case WINDOW_SEEK_CURRENT: |
| 3693 | elog(ERROR, "WINDOW_SEEK_CURRENT is not supported for WinGetFuncArgInFrame"); |
| 3694 | abs_pos = mark_pos = 0; /* keep compiler quiet */ |
| 3695 | break; |
| 3696 | case WINDOW_SEEK_HEAD: |
| 3697 | /* rejecting relpos < 0 is easy and simplifies code below */ |
| 3698 | if (relpos < 0) |
| 3699 | goto out_of_frame; |
| 3700 | update_frameheadpos(winstate); |
| 3701 | abs_pos = winstate->frameheadpos + relpos; |
| 3702 | mark_pos = abs_pos; |
| 3703 | |
| 3704 | /* |
| 3705 | * Account for exclusion option if one is active, but advance only |
| 3706 | * abs_pos not mark_pos. This prevents changes of the current |
| 3707 | * row's peer group from resulting in trying to fetch a row before |
| 3708 | * some previous mark position. |
| 3709 | * |
| 3710 | * Note that in some corner cases such as current row being |
| 3711 | * outside frame, these calculations are theoretically too simple, |
| 3712 | * but it doesn't matter because we'll end up deciding the row is |
| 3713 | * out of frame. We do not attempt to avoid fetching rows past |
| 3714 | * end of frame; that would happen in some cases anyway. |
| 3715 | */ |
| 3716 | switch (winstate->frameOptions & FRAMEOPTION_EXCLUSION) |
| 3717 | { |
| 3718 | case 0: |
| 3719 | /* no adjustment needed */ |
| 3720 | break; |
| 3721 | case FRAMEOPTION_EXCLUDE_CURRENT_ROW: |
| 3722 | if (abs_pos >= winstate->currentpos && |
| 3723 | winstate->currentpos >= winstate->frameheadpos) |
| 3724 | abs_pos++; |
| 3725 | break; |
| 3726 | case FRAMEOPTION_EXCLUDE_GROUP: |
| 3727 | update_grouptailpos(winstate); |
| 3728 | if (abs_pos >= winstate->groupheadpos && |
| 3729 | winstate->grouptailpos > winstate->frameheadpos) |
| 3730 | { |
| 3731 | int64 overlapstart = Max(winstate->groupheadpos, |
no test coverage detected