diff --git a/doc/src/sgml/catalogs.sgml b/doc/src/sgml/catalogs.sgml
index 2230c93..44d547f 100644
*** a/doc/src/sgml/catalogs.sgml
--- b/doc/src/sgml/catalogs.sgml
***************
*** 376,381 ****
--- 376,387 ----
        <entry>Transition function</entry>
       </row>
       <row>
+       <entry><structfield>agginvtransfn</structfield></entry>
+       <entry><type>regproc</type></entry>
+       <entry><literal><link linkend="catalog-pg-proc"><structname>pg_proc</structname></link>.oid</literal></entry>
+       <entry>Inverse transition function</entry>
+      </row>
+      <row>
        <entry><structfield>aggfinalfn</structfield></entry>
        <entry><type>regproc</type></entry>
        <entry><literal><link linkend="catalog-pg-proc"><structname>pg_proc</structname></link>.oid</literal></entry>
diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml
index c0a75de..51c493d 100644
*** a/doc/src/sgml/func.sgml
--- b/doc/src/sgml/func.sgml
*************** SELECT xmlagg(x) FROM (SELECT x FROM tes
*** 12885,12890 ****
--- 12885,13012 ----
     <literal>ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING</>.
     Other frame specifications can be used to obtain other effects.
    </para>
+   
+   <para>
+     Depending on the aggregate function, aggregating over frames starting
+     at a row relative to the current row can be drastically less efficient
+     than aggregating over frames aligned to the start of the partition. The
+     frame starts at a row relative to the current row if <literal>ORDER
+     BY</literal> is used together with any frame start clause other than
+     <literal>UNBOUNDED PRECEDING</literal> (which is the default). Then,
+     aggregates without a suitable <quote>inverse transition function
+     </quote> (see <xref linkend="SQL-CREATEAGGREGATE"> for details) will be
+     computed for each frame from scratch, instead of re-using the previous
+     frame's result, causing <emphasis>quadratic growth</emphasis> of the
+     execution time as the number of rows per partition increases. The table
+     <xref linkend="functions-aggregate-indframe"> list the built-in aggregate
+     functions affected by this. Note that quadratic growth is only a problem
+     if partitions contain many rows - for partitions with only a few rows,
+     even inefficient aggregates are unlikely to cause problems.
+   </para>
+ 
+   <table id="functions-aggregate-indframe">
+    <title>
+      Aggregate Function Behaviour for frames not starting at
+      <literal>UNBOUNDED PRECEDING</literal>.
+    </title>
+ 
+    <tgroup cols="3">
+      
+     <thead>
+      <row>
+       <entry>Aggregate Function</entry>
+       <entry>Input Type</entry>
+       <entry>Computed From Scratch</entry>
+      </row>
+     </thead>
+     
+     <tbody>
+       
+      <row>
+       <entry>
+        any numerical aggregate
+       </entry>
+       <entry>
+        <type>float4</type>
+        or
+        <type>float8</type>
+       </entry>
+       <entry>always, to avoid error accumulation</entry>
+      </row>
+ 
+      <row>
+       <entry>
+        any numerical aggregate
+       </entry>
+       <entry>
+        <type>numeric</type>
+       </entry>
+       <entry>if the maximum number of decimal digits within the inputs changes</entry>
+      </row>
+ 
+      <row>
+       <entry>
+        <function>min</function>
+       </entry>
+       <entry>
+        any
+       </entry>
+       <entry>if some inputs in the old frame that aren't in the new frame were minimal</entry>
+      </row>
+ 
+      <row>
+       <entry>
+        <function>max</function>
+       </entry>
+       <entry>
+         any
+       </entry>
+       <entry>if some inputs in the old frame that aren't in the new frame were maximal</entry>
+      </row>
+ 
+      <row>
+       <entry>
+        <function>bit_and</function>,<function>bit_or</function>
+       </entry>
+       <entry>
+         any
+       </entry>
+       <entry>always</entry>
+      </row>
+ 
+      <row>
+       <entry>
+        <function>string_agg</function>
+       </entry>
+       <entry>
+        <type>text</type> or
+        <type>bytea</type> or
+       </entry>
+       <entry>if the delimiter lengths vary</entry>
+      </row>
+ 
+      <row>
+       <entry>
+        <function>xmlagg</function>
+       </entry>
+       <entry>
+        <type>xml</type>
+       </entry>
+       <entry>always</entry>
+      </row>
+ 
+      <row>
+       <entry>
+        <function>json_agg</function>
+       </entry>
+       <entry>
+        <type>json</type>
+       </entry>
+       <entry>always</entry>
+      </row>
+     </tbody>
+    </tgroup>
+   </table>
  
    <note>
     <para>
diff --git a/doc/src/sgml/ref/create_aggregate.sgml b/doc/src/sgml/ref/create_aggregate.sgml
index d15fcba..aaa09a7 100644
*** a/doc/src/sgml/ref/create_aggregate.sgml
--- b/doc/src/sgml/ref/create_aggregate.sgml
*************** CREATE AGGREGATE <replaceable class="par
*** 25,30 ****
--- 25,31 ----
      SFUNC = <replaceable class="PARAMETER">sfunc</replaceable>,
      STYPE = <replaceable class="PARAMETER">state_data_type</replaceable>
      [ , SSPACE = <replaceable class="PARAMETER">state_data_size</replaceable> ]
+     [ , INVFUNC = <replaceable class="PARAMETER">inv_trans_func</replaceable> ]
      [ , FINALFUNC = <replaceable class="PARAMETER">ffunc</replaceable> ]
      [ , INITCOND = <replaceable class="PARAMETER">initial_condition</replaceable> ]
      [ , SORTOP = <replaceable class="PARAMETER">sort_operator</replaceable> ]
*************** CREATE AGGREGATE <replaceable class="PAR
*** 47,52 ****
--- 48,54 ----
      SFUNC = <replaceable class="PARAMETER">sfunc</replaceable>,
      STYPE = <replaceable class="PARAMETER">state_data_type</replaceable>
      [ , SSPACE = <replaceable class="PARAMETER">state_data_size</replaceable> ]
+     [ , INVFUNC = <replaceable class="PARAMETER">inv_trans_func</replaceable> ]
      [ , FINALFUNC = <replaceable class="PARAMETER">ffunc</replaceable> ]
      [ , INITCOND = <replaceable class="PARAMETER">initial_condition</replaceable> ]
      [ , SORTOP = <replaceable class="PARAMETER">sort_operator</replaceable> ]
*************** CREATE AGGREGATE <replaceable class="PAR
*** 84,98 ****
    </para>
  
    <para>
!    An aggregate function is made from one or two ordinary
     functions:
!    a state transition function
     <replaceable class="PARAMETER">sfunc</replaceable>,
     and an optional final calculation function
     <replaceable class="PARAMETER">ffunc</replaceable>.
     These are used as follows:
  <programlisting>
  <replaceable class="PARAMETER">sfunc</replaceable>( internal-state, next-data-values ) ---> next-internal-state
  <replaceable class="PARAMETER">ffunc</replaceable>( internal-state ) ---> aggregate-value
  </programlisting>
    </para>
--- 86,103 ----
    </para>
  
    <para>
!    An aggregate function is made from one, two or three ordinary
     functions:
!    a (forward) state transition function
     <replaceable class="PARAMETER">sfunc</replaceable>,
+    an optional inverse state transition function
+    <replaceable class="PARAMETER">invfunc</replaceable>,
     and an optional final calculation function
     <replaceable class="PARAMETER">ffunc</replaceable>.
     These are used as follows:
  <programlisting>
  <replaceable class="PARAMETER">sfunc</replaceable>( internal-state, next-data-values ) ---> next-internal-state
+ <replaceable class="PARAMETER">invfunc</replaceable>( internal-state, data-values ) ---> internal-state-without-data-values
  <replaceable class="PARAMETER">ffunc</replaceable>( internal-state ) ---> aggregate-value
  </programlisting>
    </para>
*************** CREATE AGGREGATE <replaceable class="PAR
*** 102,113 ****
     of data type <replaceable class="PARAMETER">stype</replaceable>
     to hold the current internal state of the aggregate.  At each input row,
     the aggregate argument value(s) are calculated and
!    the state transition function is invoked with the current state value
     and the new argument value(s) to calculate a new
!    internal state value.  After all the rows have been processed,
!    the final function is invoked once to calculate the aggregate's return
!    value.  If there is no final function then the ending state value
!    is returned as-is.
    </para>
  
    <para>
--- 107,134 ----
     of data type <replaceable class="PARAMETER">stype</replaceable>
     to hold the current internal state of the aggregate.  At each input row,
     the aggregate argument value(s) are calculated and
!    the forward state transition function is invoked with the current state value
     and the new argument value(s) to calculate a new
!    internal state value.
!    If the aggregate is computed over a sliding frame, i.e. if it is used as a
!    <firstterm>window function</firstterm>, the inverse transition function is
!    used to undo the effect of a previous invocation of the forward transition
!    function once argument value(s) fall out of the sliding frame.
!    Conceptually, the forward transition functions thus adds some input
!    value(s) to the state, and the inverse transition functions removes them
!    again. Values are, if they are removed, always removed in the same order
!    they were added, without gaps. Whenever the inverse transition function is
!    invoked, it will thus receive the earliest added but not yet removed
!    argument value(s). If no inverse transition function is supplied, the
!    aggregate can still be used to aggregate over sliding frames, but with
!    reduced efficiency. <productname>PostgreSQL</productname> will then
!    recompute the whole aggregation whenever the start of the frame moves. To
!    calculate the aggregate's return value, the final function is invoked on
!    the ending state value. If there is no final function then ending state
!    value is returned as-is. Either way, the result is assumed to reflect the
!    aggregation of all values added but not yet removed from the state value.
!    Note that if the aggregate is used as a window function, the aggregation
!    may be continued after the final function has been called.
    </para>
  
    <para>
*************** CREATE AGGREGATE <replaceable class="PAR
*** 127,135 ****
     is retained).  If the initial state value is null, then at the first row
     with all-nonnull input values, the first argument value replaces the state
     value, and the transition function is invoked at subsequent rows with
!    all-nonnull input values.
!    This is handy for implementing aggregates like <function>max</function>.
!    Note that this behavior is only available when
     <replaceable class="PARAMETER">state_data_type</replaceable>
     is the same as the first
     <replaceable class="PARAMETER">arg_data_type</replaceable>.
--- 148,164 ----
     is retained).  If the initial state value is null, then at the first row
     with all-nonnull input values, the first argument value replaces the state
     value, and the transition function is invoked at subsequent rows with
!    all-nonnull input values. Should inputs later need to be removed again, the
!    inverse transition function (if present) is used as long as some non-null
!    inputs remain part of the state value. In particular, even if the initial
!    state value is null, the inverse transition function might be used to remove
!    the first non-null input, even though that input was never passed to the
!    forward transition function, but instead just replaced the initial state!
!    The last non-null input, however, is not removed by invoking the inverse
!    transition function, but instead the state is simply reset to its initial
!    value. This is handy for implementing aggregates like <function>max</function>.
!    Note that turning the first non-null input into the initial state is only
!    possible when
     <replaceable class="PARAMETER">state_data_type</replaceable>
     is the same as the first
     <replaceable class="PARAMETER">arg_data_type</replaceable>.
*************** CREATE AGGREGATE <replaceable class="PAR
*** 138,147 ****
    </para>
  
    <para>
!    If the state transition function is not strict, then it will be called
!    unconditionally at each input row, and must deal with null inputs
!    and null state values for itself.  This allows the aggregate
!    author to have full control over the aggregate's handling of null values.
    </para>
  
    <para>
--- 167,206 ----
    </para>
  
    <para>
!     If the forward transition function is not declared <quote>strict</quote>,
!     but the inverse transition function is, null input values are still not
!     passed to either the forward or the inverse transition function. The
!     system then behaves as it would for a strict forward transition function,
!     except that initial value null isn't handled specially, i.e. isn't
!     replaced by the first argument of the first non-null input. Instead the
!     forward transition function is simply invoked with a null state and
!     non-null argument values. So in effect, in this case the forward
!     transition function is being treated as non-strict in the state argument
!     but strict in all argument values.
!   </para> 
! 
!   <para>
!    If the state transition function is not <quote>strict</quote>, and either
!    no inverse was provided or is also not strict, then it will be called
!    unconditionally at each input row, and must deal with null inputs and null
!    state values for itself. The same goes for the inverse transition function.
!    This allows the aggregate author to have full control over the
!    aggregate's handling of null argument values.
!   </para>
!   
!   <para>
!     The inverse transition function can signal by returning null that it is
!     unable to remove a particular input value from a particular state.
!     <productname>PostgreSQL</productname> will then act as if no inverse
!     transition function had been supplied, i.e. it will recompute the whole
!     aggregation, starting with the first argument value that it would not have
!     removed. That allows aggregates like <function>max</function> to still
!     avoid redoing the whole aggregation in <emphasis>some</emphasis> cases,
!     without paying the overhead of tracking enough state to be able to avoid
!     them in <emphasis>all</emphasis> cases. This demands, however, that
!     null isn't used as a valid state value, except as the initial state. If
!     an aggregate provides an inverse transition function, it is therefore an
!     error for the forward transition function to return null.
    </para>
  
    <para>
*************** SELECT col FROM tab ORDER BY col USING s
*** 271,277 ****
      <term><replaceable class="PARAMETER">sfunc</replaceable></term>
      <listitem>
       <para>
!       The name of the state transition function to be called for each
        input row.  For a normal <replaceable class="PARAMETER">N</>-argument
        aggregate function, the <replaceable class="PARAMETER">sfunc</>
        must take <replaceable class="PARAMETER">N</>+1 arguments,
--- 330,336 ----
      <term><replaceable class="PARAMETER">sfunc</replaceable></term>
      <listitem>
       <para>
!       The name of the (forward) state transition function to be called for each
        input row.  For a normal <replaceable class="PARAMETER">N</>-argument
        aggregate function, the <replaceable class="PARAMETER">sfunc</>
        must take <replaceable class="PARAMETER">N</>+1 arguments,
*************** SELECT col FROM tab ORDER BY col USING s
*** 281,287 ****
        The function must return a value of type <replaceable
        class="PARAMETER">state_data_type</replaceable>.  This function
        takes the current state value and the current input data value(s),
!       and returns the next state value.
       </para>
  
       <para>
--- 340,348 ----
        The function must return a value of type <replaceable
        class="PARAMETER">state_data_type</replaceable>.  This function
        takes the current state value and the current input data value(s),
!       and returns the next state value. Note that if an inverse
!       transition function is present, the forward transition function must
!       not return <literal>NULL</>
       </para>
  
       <para>
*************** SELECT col FROM tab ORDER BY col USING s
*** 294,299 ****
--- 355,384 ----
     </varlistentry>
  
     <varlistentry>
+     <term><replaceable class="PARAMETER">invfunc</replaceable></term>
+     <listitem>
+      <para>
+       The name of the inverse state transition function to be called for each
+       input row.  For a normal <replaceable class="PARAMETER">N</>-argument
+       aggregate function, the <replaceable class="PARAMETER">sfunc</>
+       must take <replaceable class="PARAMETER">N</>+1 arguments,
+       the first being of type <replaceable
+       class="PARAMETER">state_data_type</replaceable> and the rest
+       matching the declared input data type(s) of the aggregate.
+       The function must return a value of type <replaceable
+       class="PARAMETER">state_data_type</replaceable>. These are the same
+       demands placed on the forward transition function, meaning that the
+       signatures of the two functions must be identical. Their
+       <quote>strictness</quote> though may differ, but the only allowed
+       combination is a non-strict forward combined with a strict inverse
+       transition function. The inverse transition function may return
+       <literal>NULL</> to force the aggregation to be restarted from
+       scratch.
+      </para>
+     </listitem>
+    </varlistentry>
+ 
+    <varlistentry>
      <term><replaceable class="PARAMETER">state_data_type</replaceable></term>
      <listitem>
       <para>
diff --git a/doc/src/sgml/xaggr.sgml b/doc/src/sgml/xaggr.sgml
index e77ef12..397e398 100644
*** a/doc/src/sgml/xaggr.sgml
--- b/doc/src/sgml/xaggr.sgml
***************
*** 16,22 ****
     as each successive input row is processed.
     To define a new aggregate
     function, one selects a data type for the state value,
!    an initial value for the state, and a state transition
     function.  The state transition function takes the previous state
     value and the aggregate's input value(s) for the current row, and
     returns a new state value.
--- 16,22 ----
     as each successive input row is processed.
     To define a new aggregate
     function, one selects a data type for the state value,
!    an initial value for the state, and a forward state transition
     function.  The state transition function takes the previous state
     value and the aggregate's input value(s) for the current row, and
     returns a new state value.
***************
*** 24,30 ****
     can also be specified, in case the desired result of the aggregate
     is different from the data that needs to be kept in the running
     state value.  The final function takes the last state value
!    and returns whatever is wanted as the aggregate result.
     In principle, the transition and final functions are just ordinary
     functions that could also be used outside the context of the
     aggregate.  (In practice, it's often helpful for performance reasons
--- 24,42 ----
     can also be specified, in case the desired result of the aggregate
     is different from the data that needs to be kept in the running
     state value.  The final function takes the last state value
!    and returns whatever is wanted as the aggregate result. 
!    To enable efficient evaluation of an aggregate used as a window function
!    with a sliding frame (i.e. a frame that starts relative to the current row),
!    an aggregate can optionally provide an inverse state transition function.
!    The inverse transition function takes the the current state and the
!    aggregate's input value(s) for the <emphasis>earliest</emphasis> row passed
!    to the forward transition function, and returns a state equivalent to what
!    the current state had been had the forward transition function never been
!    invoked for that earliest row, only for all rows that followed it. Thus,
!    if an inverse transition function is provided, the rows that were part of
!    the previous row's frame but not of the current row's frame can simply be
!    removed from the state instead of having to redo the whole aggregation
!    over the new frame.
     In principle, the transition and final functions are just ordinary
     functions that could also be used outside the context of the
     aggregate.  (In practice, it's often helpful for performance reasons
*************** CREATE AGGREGATE avg (float8)
*** 132,137 ****
--- 144,188 ----
    </note>
  
    <para>
+    When providing an inverse transition function, care should be taken to
+    ensure that it doesn't introduce unexpected user-visible differences
+    between results obtained by reaggregating all inputs vs. using the inverse
+    transition function. An example for an aggregate where adding an inverse
+    transition function seems easy at first, yet were doing so would violate
+    this requirement is <function>sum</> over <type>float</> or
+    <type>double precision</>. A naive declaration of
+    <function>sum(<type>float</>)</function> could be
+    
+    <programlisting>
+    CREATE AGGREGATE unsafe_sum (float8)
+    (
+        stype = float8,
+        sfunc = float8pl,
+        invfunc = float8mi
+    );
+    </programlisting>
+    
+    This aggregate, howevery, can give wildly different results than it would
+    have without the inverse transition function. For example, consider
+    
+    <programlisting>
+    SELECT
+      unsafe_sum(x) OVER (ORDER BY n ROWS BETWEEN CURRENT ROW AND
+                                                  1 FOLLOWING)
+    FROM (VALUES
+      (1, 1.0e20::float8),
+      (2, 1.0::float8)
+    ) AS v (n,x)
+    </programlisting>
+    
+    which returns 0 as it's second result, yet the expected answer is 1. The
+    reason for this is the limited precision of floating point types - adding
+    1 to 1e20 actually leaves the value unchanged, and so substracting 1e20
+    again yields 0, not 1. Note that this is a limitation of floating point
+    types in general and not a limitation of <productname>PostgreSQL</>.
+   </para>
+   
+   <para>
     Aggregate functions can use polymorphic
     state transition functions or final functions, so that the same functions
     can be used to implement multiple aggregates.
