Adding an aggregate function requires some additional effort as an aggregate
function on the SQL level is actually implemented by a small family of C
functions and private data passed between them.
Aggregate private data is declared using the <data> tag.
For each aggregate group it is initialized by the code given in
<clear>. For each row of the group the <add> code is
executed, receiving the declared <parameter>s just like a
normal function. Finally the <result> code is executed and
expected to pass the functions.
See the following example for a simple reimplementation of the
standard AVG() function:
<?xml version="1.0"?>
<udf name="x4">
<maintainer>
<name>Hartmut Holzgraefe</name>
<email>hartmut@php.net</email>
</maintainer>
<license>LGPL</license>
<function name="ex_avg" type="aggregate" returns="real" null="yes">
<param name="x" type="real"/>
<data>
<element name="count" type="int" default="0"/>
<element name="sum_x" type="real" default="0.0"/>
</data>
<clear>
<![CDATA[
data->count = 0;
data->sum_x = 0.0;
]]>
</clear>
<add>
<![CDATA[
if (!x_is_null) {
data->count++;
data->sum_x += x;
}
]]>
</add>
<result>
<![CDATA[
if (data->count < 1)
{
*is_null = 1;
return 0.0;
}
*is_null = 0;
return data->sum_x / data->count;
]]>
</result>
</function>
</udf>