@@ -2032,6 +2032,82 @@ update_grouptailpos(WindowAggState *winstate)
2032
2032
MemoryContextSwitchTo (oldcontext );
2033
2033
}
2034
2034
2035
+ /*
2036
+ * calculate_frame_offsets
2037
+ * Determine the startOffsetValue and endOffsetValue values for the
2038
+ * WindowAgg's frame options.
2039
+ */
2040
+ static pg_noinline void
2041
+ calculate_frame_offsets (PlanState * pstate )
2042
+ {
2043
+ WindowAggState * winstate = castNode (WindowAggState , pstate );
2044
+ ExprContext * econtext ;
2045
+ int frameOptions = winstate -> frameOptions ;
2046
+ Datum value ;
2047
+ bool isnull ;
2048
+ int16 len ;
2049
+ bool byval ;
2050
+
2051
+ /* Ensure we've not been called before for this scan */
2052
+ Assert (winstate -> all_first );
2053
+
2054
+ econtext = winstate -> ss .ps .ps_ExprContext ;
2055
+
2056
+ if (frameOptions & FRAMEOPTION_START_OFFSET )
2057
+ {
2058
+ Assert (winstate -> startOffset != NULL );
2059
+ value = ExecEvalExprSwitchContext (winstate -> startOffset ,
2060
+ econtext ,
2061
+ & isnull );
2062
+ if (isnull )
2063
+ ereport (ERROR ,
2064
+ (errcode (ERRCODE_NULL_VALUE_NOT_ALLOWED ),
2065
+ errmsg ("frame starting offset must not be null" )));
2066
+ /* copy value into query-lifespan context */
2067
+ get_typlenbyval (exprType ((Node * ) winstate -> startOffset -> expr ),
2068
+ & len ,
2069
+ & byval );
2070
+ winstate -> startOffsetValue = datumCopy (value , byval , len );
2071
+ if (frameOptions & (FRAMEOPTION_ROWS | FRAMEOPTION_GROUPS ))
2072
+ {
2073
+ /* value is known to be int8 */
2074
+ int64 offset = DatumGetInt64 (value );
2075
+
2076
+ if (offset < 0 )
2077
+ ereport (ERROR ,
2078
+ (errcode (ERRCODE_INVALID_PRECEDING_OR_FOLLOWING_SIZE ),
2079
+ errmsg ("frame starting offset must not be negative" )));
2080
+ }
2081
+ }
2082
+
2083
+ if (frameOptions & FRAMEOPTION_END_OFFSET )
2084
+ {
2085
+ Assert (winstate -> endOffset != NULL );
2086
+ value = ExecEvalExprSwitchContext (winstate -> endOffset ,
2087
+ econtext ,
2088
+ & isnull );
2089
+ if (isnull )
2090
+ ereport (ERROR ,
2091
+ (errcode (ERRCODE_NULL_VALUE_NOT_ALLOWED ),
2092
+ errmsg ("frame ending offset must not be null" )));
2093
+ /* copy value into query-lifespan context */
2094
+ get_typlenbyval (exprType ((Node * ) winstate -> endOffset -> expr ),
2095
+ & len ,
2096
+ & byval );
2097
+ winstate -> endOffsetValue = datumCopy (value , byval , len );
2098
+ if (frameOptions & (FRAMEOPTION_ROWS | FRAMEOPTION_GROUPS ))
2099
+ {
2100
+ /* value is known to be int8 */
2101
+ int64 offset = DatumGetInt64 (value );
2102
+
2103
+ if (offset < 0 )
2104
+ ereport (ERROR ,
2105
+ (errcode (ERRCODE_INVALID_PRECEDING_OR_FOLLOWING_SIZE ),
2106
+ errmsg ("frame ending offset must not be negative" )));
2107
+ }
2108
+ }
2109
+ winstate -> all_first = false;
2110
+ }
2035
2111
2036
2112
/* -----------------
2037
2113
* ExecWindowAgg
@@ -2061,68 +2137,8 @@ ExecWindowAgg(PlanState *pstate)
2061
2137
* rescan). These are assumed to hold constant throughout the scan; if
2062
2138
* user gives us a volatile expression, we'll only use its initial value.
2063
2139
*/
2064
- if (winstate -> all_first )
2065
- {
2066
- int frameOptions = winstate -> frameOptions ;
2067
- Datum value ;
2068
- bool isnull ;
2069
- int16 len ;
2070
- bool byval ;
2071
-
2072
- econtext = winstate -> ss .ps .ps_ExprContext ;
2073
-
2074
- if (frameOptions & FRAMEOPTION_START_OFFSET )
2075
- {
2076
- Assert (winstate -> startOffset != NULL );
2077
- value = ExecEvalExprSwitchContext (winstate -> startOffset ,
2078
- econtext ,
2079
- & isnull );
2080
- if (isnull )
2081
- ereport (ERROR ,
2082
- (errcode (ERRCODE_NULL_VALUE_NOT_ALLOWED ),
2083
- errmsg ("frame starting offset must not be null" )));
2084
- /* copy value into query-lifespan context */
2085
- get_typlenbyval (exprType ((Node * ) winstate -> startOffset -> expr ),
2086
- & len , & byval );
2087
- winstate -> startOffsetValue = datumCopy (value , byval , len );
2088
- if (frameOptions & (FRAMEOPTION_ROWS | FRAMEOPTION_GROUPS ))
2089
- {
2090
- /* value is known to be int8 */
2091
- int64 offset = DatumGetInt64 (value );
2092
-
2093
- if (offset < 0 )
2094
- ereport (ERROR ,
2095
- (errcode (ERRCODE_INVALID_PRECEDING_OR_FOLLOWING_SIZE ),
2096
- errmsg ("frame starting offset must not be negative" )));
2097
- }
2098
- }
2099
- if (frameOptions & FRAMEOPTION_END_OFFSET )
2100
- {
2101
- Assert (winstate -> endOffset != NULL );
2102
- value = ExecEvalExprSwitchContext (winstate -> endOffset ,
2103
- econtext ,
2104
- & isnull );
2105
- if (isnull )
2106
- ereport (ERROR ,
2107
- (errcode (ERRCODE_NULL_VALUE_NOT_ALLOWED ),
2108
- errmsg ("frame ending offset must not be null" )));
2109
- /* copy value into query-lifespan context */
2110
- get_typlenbyval (exprType ((Node * ) winstate -> endOffset -> expr ),
2111
- & len , & byval );
2112
- winstate -> endOffsetValue = datumCopy (value , byval , len );
2113
- if (frameOptions & (FRAMEOPTION_ROWS | FRAMEOPTION_GROUPS ))
2114
- {
2115
- /* value is known to be int8 */
2116
- int64 offset = DatumGetInt64 (value );
2117
-
2118
- if (offset < 0 )
2119
- ereport (ERROR ,
2120
- (errcode (ERRCODE_INVALID_PRECEDING_OR_FOLLOWING_SIZE ),
2121
- errmsg ("frame ending offset must not be negative" )));
2122
- }
2123
- }
2124
- winstate -> all_first = false;
2125
- }
2140
+ if (unlikely (winstate -> all_first ))
2141
+ calculate_frame_offsets (pstate );
2126
2142
2127
2143
/* We need to loop as the runCondition or qual may filter out tuples */
2128
2144
for (;;)
0 commit comments