@@ -27,6 +27,7 @@ CREATE AGGREGATE <replaceable class="parameter">name</replaceable> ( [ <replacea
2727 [ , SSPACE = <replaceable class="parameter">state_data_size</replaceable> ]
2828 [ , FINALFUNC = <replaceable class="parameter">ffunc</replaceable> ]
2929 [ , FINALFUNC_EXTRA ]
30+ [ , FINALFUNC_MODIFY = { READ_ONLY | SHARABLE | READ_WRITE } ]
3031 [ , COMBINEFUNC = <replaceable class="parameter">combinefunc</replaceable> ]
3132 [ , SERIALFUNC = <replaceable class="parameter">serialfunc</replaceable> ]
3233 [ , DESERIALFUNC = <replaceable class="parameter">deserialfunc</replaceable> ]
@@ -37,6 +38,7 @@ CREATE AGGREGATE <replaceable class="parameter">name</replaceable> ( [ <replacea
3738 [ , MSSPACE = <replaceable class="parameter">mstate_data_size</replaceable> ]
3839 [ , MFINALFUNC = <replaceable class="parameter">mffunc</replaceable> ]
3940 [ , MFINALFUNC_EXTRA ]
41+ [ , MFINALFUNC_MODIFY = { READ_ONLY | SHARABLE | READ_WRITE } ]
4042 [ , MINITCOND = <replaceable class="parameter">minitial_condition</replaceable> ]
4143 [ , SORTOP = <replaceable class="parameter">sort_operator</replaceable> ]
4244 [ , PARALLEL = { SAFE | RESTRICTED | UNSAFE } ]
@@ -49,6 +51,7 @@ CREATE AGGREGATE <replaceable class="parameter">name</replaceable> ( [ [ <replac
4951 [ , SSPACE = <replaceable class="parameter">state_data_size</replaceable> ]
5052 [ , FINALFUNC = <replaceable class="parameter">ffunc</replaceable> ]
5153 [ , FINALFUNC_EXTRA ]
54+ [ , FINALFUNC_MODIFY = { READ_ONLY | SHARABLE | READ_WRITE } ]
5255 [ , INITCOND = <replaceable class="parameter">initial_condition</replaceable> ]
5356 [ , PARALLEL = { SAFE | RESTRICTED | UNSAFE } ]
5457 [ , HYPOTHETICAL ]
@@ -63,6 +66,7 @@ CREATE AGGREGATE <replaceable class="parameter">name</replaceable> (
6366 [ , SSPACE = <replaceable class="parameter">state_data_size</replaceable> ]
6467 [ , FINALFUNC = <replaceable class="parameter">ffunc</replaceable> ]
6568 [ , FINALFUNC_EXTRA ]
69+ [ , FINALFUNC_MODIFY = { READ_ONLY | SHARABLE | READ_WRITE } ]
6670 [ , COMBINEFUNC = <replaceable class="parameter">combinefunc</replaceable> ]
6771 [ , SERIALFUNC = <replaceable class="parameter">serialfunc</replaceable> ]
6872 [ , DESERIALFUNC = <replaceable class="parameter">deserialfunc</replaceable> ]
@@ -73,6 +77,7 @@ CREATE AGGREGATE <replaceable class="parameter">name</replaceable> (
7377 [ , MSSPACE = <replaceable class="parameter">mstate_data_size</replaceable> ]
7478 [ , MFINALFUNC = <replaceable class="parameter">mffunc</replaceable> ]
7579 [ , MFINALFUNC_EXTRA ]
80+ [ , MFINALFUNC_MODIFY = { READ_ONLY | SHARABLE | READ_WRITE } ]
7681 [ , MINITCOND = <replaceable class="parameter">minitial_condition</replaceable> ]
7782 [ , SORTOP = <replaceable class="parameter">sort_operator</replaceable> ]
7883)
@@ -197,7 +202,8 @@ CREATE AGGREGATE <replaceable class="parameter">name</replaceable> (
197202 as described in <xref linkend="xaggr-moving-aggregates">. This requires
198203 specifying the <literal>MSFUNC</>, <literal>MINVFUNC</>,
199204 and <literal>MSTYPE</> parameters, and optionally
200- the <literal>MSPACE</>, <literal>MFINALFUNC</>, <literal>MFINALFUNC_EXTRA</>,
205+ the <literal>MSPACE</>, <literal>MFINALFUNC</>,
206+ <literal>MFINALFUNC_EXTRA</>, <literal>MFINALFUNC_MODIFY</>,
201207 and <literal>MINITCOND</> parameters. Except for <literal>MINVFUNC</>,
202208 these parameters work like the corresponding simple-aggregate parameters
203209 without <literal>M</>; they define a separate implementation of the
@@ -412,6 +418,21 @@ SELECT col FROM tab ORDER BY col USING sortop LIMIT 1;
412418 </listitem>
413419 </varlistentry>
414420
421+ <varlistentry>
422+ <term><literal>FINALFUNC_MODIFY</> = { <literal>READ_ONLY</> | <literal>SHARABLE</> | <literal>READ_WRITE</> }</term>
423+ <listitem>
424+ <para>
425+ This option specifies whether the final function is a pure function
426+ that does not modify its arguments. <literal>READ_ONLY</> indicates
427+ it does not; the other two values indicate that it may change the
428+ transition state value. See <xref linkend="sql-createaggregate-notes"
429+ endterm="sql-createaggregate-notes-title"> below for more detail. The
430+ default is <literal>READ_ONLY</>, except for ordered-set aggregates,
431+ for which the default is <literal>READ_WRITE</>.
432+ </para>
433+ </listitem>
434+ </varlistentry>
435+
415436 <varlistentry>
416437 <term><replaceable class="parameter">combinefunc</replaceable></term>
417438 <listitem>
@@ -563,6 +584,16 @@ SELECT col FROM tab ORDER BY col USING sortop LIMIT 1;
563584 </listitem>
564585 </varlistentry>
565586
587+ <varlistentry>
588+ <term><literal>MFINALFUNC_MODIFY</> = { <literal>READ_ONLY</> | <literal>SHARABLE</> | <literal>READ_WRITE</> }</term>
589+ <listitem>
590+ <para>
591+ This option is like <literal>FINALFUNC_MODIFY</>, but it describes
592+ the behavior of the moving-aggregate final function.
593+ </para>
594+ </listitem>
595+ </varlistentry>
596+
566597 <varlistentry>
567598 <term><replaceable class="parameter">minitial_condition</replaceable></term>
568599 <listitem>
@@ -587,12 +618,12 @@ SELECT col FROM tab ORDER BY col USING sortop LIMIT 1;
587618 </varlistentry>
588619
589620 <varlistentry>
590- <term><literal>PARALLEL</ literal></term>
621+ <term><literal>PARALLEL =</> { < literal>SAFE</> | <literal>RESTRICTED</> | <literal>UNSAFE</> } </term>
591622 <listitem>
592623 <para>
593624 The meanings of <literal>PARALLEL SAFE</>, <literal>PARALLEL
594625 RESTRICTED</>, and <literal>PARALLEL UNSAFE</> are the same as
595- for <xref linkend="sql-createfunction">. An aggregate will not be
626+ in <xref linkend="sql-createfunction">. An aggregate will not be
596627 considered for parallelization if it is marked <literal>PARALLEL
597628 UNSAFE</> (which is the default!) or <literal>PARALLEL RESTRICTED</>.
598629 Note that the parallel-safety markings of the aggregate's support
@@ -624,8 +655,8 @@ SELECT col FROM tab ORDER BY col USING sortop LIMIT 1;
624655 </para>
625656 </refsect1>
626657
627- <refsect1>
628- <title>Notes</title>
658+ <refsect1 id="sql-createaggregate-notes" >
659+ <title id="sql-createaggregate-notes-title" >Notes</title>
629660
630661 <para>
631662 In parameters that specify support function names, you can write
@@ -634,6 +665,34 @@ SELECT col FROM tab ORDER BY col USING sortop LIMIT 1;
634665 of the support functions are determined from other parameters.
635666 </para>
636667
668+ <para>
669+ Ordinarily, Postgres functions are expected to be true functions that
670+ do not modify their input values. However, an aggregate transition
671+ function, <emphasis>when used in the context of an aggregate</>,
672+ is allowed to cheat and modify its transition-state argument in place.
673+ This can provide substantial performance benefits compared to making
674+ a fresh copy of the transition state each time.
675+ </para>
676+
677+ <para>
678+ Likewise, while an aggregate final function is normally expected not to
679+ modify its input values, sometimes it is impractical to avoid modifying
680+ the transition-state argument. Such behavior must be declared using
681+ the <literal>FINALFUNC_MODIFY</> parameter. The <literal>READ_WRITE</>
682+ value indicates that the final function modifies the transition state in
683+ unspecified ways. This value prevents use of the aggregate as a window
684+ function, and it also prevents merging of transition states for aggregate
685+ calls that share the same input values and transition functions.
686+ The <literal>SHARABLE</> value indicates that the transition function
687+ cannot be applied after the final function, but multiple final-function
688+ calls can be performed on the ending transition state value. This value
689+ prevents use of the aggregate as a window function, but it allows merging
690+ of transition states. (That is, the optimization of interest here is not
691+ applying the same final function repeatedly, but applying different final
692+ functions to the same ending transition state value. This is allowed as
693+ long as none of the final functions are marked <literal>READ_WRITE</>.)
694+ </para>
695+
637696 <para>
638697 If an aggregate supports moving-aggregate mode, it will improve
639698 calculation efficiency when the aggregate is used as a window function
@@ -671,7 +730,8 @@ SELECT col FROM tab ORDER BY col USING sortop LIMIT 1;
671730 Note that whether or not the aggregate supports moving-aggregate
672731 mode, <productname>PostgreSQL</productname> can handle a moving frame
673732 end without recalculation; this is done by continuing to add new values
674- to the aggregate's state. It is assumed that the final function does
733+ to the aggregate's state. This is why use of an aggregate as a window
734+ function requires that the final function be read-only: it must
675735 not damage the aggregate's state value, so that the aggregation can be
676736 continued even after an aggregate result value has been obtained for
677737 one set of frame boundaries.
0 commit comments