* update_frametailpos * make frametailpos valid for the current row * * Note that frametailpos is computed without regard for any window exclusion * clause; the current row and/or its peers are considered part of the frame * for this purpose even if they must be excluded later. * * May clobber winstate->temp_slot_2. */
| 1990 | * May clobber winstate->temp_slot_2. |
| 1991 | */ |
| 1992 | static void |
| 1993 | update_frametailpos(WindowAggState *winstate) |
| 1994 | { |
| 1995 | WindowAgg *node = (WindowAgg *) winstate->ss.ps.plan; |
| 1996 | int frameOptions = winstate->frameOptions; |
| 1997 | MemoryContext oldcontext; |
| 1998 | |
| 1999 | if (winstate->frametail_valid) |
| 2000 | return; /* already known for current row */ |
| 2001 | |
| 2002 | /* We may be called in a short-lived context */ |
| 2003 | oldcontext = MemoryContextSwitchTo(winstate->ss.ps.ps_ExprContext->ecxt_per_query_memory); |
| 2004 | |
| 2005 | compute_start_end_offsets(winstate); |
| 2006 | |
| 2007 | if (frameOptions & FRAMEOPTION_END_UNBOUNDED_FOLLOWING) |
| 2008 | { |
| 2009 | /* In UNBOUNDED FOLLOWING mode, all partition rows are in frame */ |
| 2010 | spool_tuples(winstate, -1); |
| 2011 | winstate->frametailpos = winstate->spooled_rows; |
| 2012 | winstate->frametail_valid = true; |
| 2013 | } |
| 2014 | else if (frameOptions & FRAMEOPTION_END_CURRENT_ROW) |
| 2015 | { |
| 2016 | if (frameOptions & FRAMEOPTION_ROWS) |
| 2017 | { |
| 2018 | /* In ROWS mode, exactly the rows up to current are in frame */ |
| 2019 | winstate->frametailpos = winstate->currentpos + 1; |
| 2020 | winstate->frametail_valid = true; |
| 2021 | } |
| 2022 | else if (frameOptions & (FRAMEOPTION_RANGE | FRAMEOPTION_GROUPS)) |
| 2023 | { |
| 2024 | /* If no ORDER BY, all rows are peers with each other */ |
| 2025 | if (node->ordNumCols == 0) |
| 2026 | { |
| 2027 | spool_tuples(winstate, -1); |
| 2028 | winstate->frametailpos = winstate->spooled_rows; |
| 2029 | winstate->frametail_valid = true; |
| 2030 | MemoryContextSwitchTo(oldcontext); |
| 2031 | return; |
| 2032 | } |
| 2033 | |
| 2034 | /* |
| 2035 | * In RANGE or GROUPS END_CURRENT_ROW mode, frame end is the last |
| 2036 | * row that is a peer of current row, frame tail is the row after |
| 2037 | * that (if any). We keep a copy of the last-known frame tail row |
| 2038 | * in frametail_slot, and advance as necessary. Note that if we |
| 2039 | * reach end of partition, we will leave frametailpos = end+1 and |
| 2040 | * frametail_slot empty. |
| 2041 | */ |
| 2042 | tuplestore_select_read_pointer(winstate->buffer, |
| 2043 | winstate->frametail_ptr); |
| 2044 | if (winstate->frametailpos == 0 && |
| 2045 | TupIsNull(winstate->frametail_slot)) |
| 2046 | { |
| 2047 | /* fetch first row into frametail_slot, if we didn't already */ |
| 2048 | if (!tuplestore_gettupleslot(winstate->buffer, true, true, |
| 2049 | winstate->frametail_slot)) |
no test coverage detected