The SUMSQ user-defined aggregate
The SUMSQ user-defined aggregate squares each value and calculates the sum of these squared values.
x12 + x22 + ...
where
each xi is one column value; that is, one aggregate
argument.- Square the aggregate argument.
The ITER function has access to the aggregate argument because the database server passes it in. Therefore, ITER does not require additional information to perform this step.
- Add the squared argument to the partial sum of previous squared
values.
To add in the squared argument, the aggregate must keep a partial sum of the previous squared values. For the ITER function to have access to the partial sum from the previous iterations, the aggregate state must contain it.
- The INIT support function does not need to perform state management.
An aggregate with a simple state does not need to explicitly handle the allocation and deallocation of the aggregate state. Instead, the database server automatically allocates the aggregate state and initializes it to NULL. Therefore, the INIT function does not require other INIT-function tasks (see Table 1). Therefore, this support function can safely be omitted from the aggregate definition.
- The COMBINE support function can be the same as its ITER function.
No special processing is required to merge two partial states. The ITER function can adequately perform this merge.
Before the iterations begin, the partial sum needs to be initialized to zero. However, because the INIT function is not required for state management, this aggregate initializes the state in the first invocation of its ITER function. The ITER function then calculates the square of a single aggregate argument, and adds this value to a partial sum. When the last iteration is reached, the final partial sum is the value that the SUMSQ aggregate returns. Therefore, the SUMSQ algorithm does not require a FINAL function for post-iteration tasks.
/* SUMSQ ITER support function on INTEGER */
mi_integer iter_sumsq(state, value, fparam)
mi_integer state;
mi_integer value;
MI_FPARAM *fparam;
{
/* If 'state' is NULL, this is the first invocation.
* Just return square of 'value'.
*/
if ( mi_fp_argisnull(fparam, 0) )
return (value * value);
else /* add 'state' and square of 'value' together */
return (state + (value * value));
}
/* SUMSQ COMBINE support function on INTEGER */
mi_integer combine_sumsq(state1, state2)
mi_integer state1, state2;
{
/* Return the new partial sum from two parallel partial
* sums
*/
return (iter_sumsq(state1, state2));
}
CREATE AGGREGATE sumsq
WITH (ITER = iter_sumsq,
COMBINE = combine_sumsq);
This CREATE AGGREGATE statement lists only the aggregate support functions that are required to implement SUMSQ: ITER and COMBINE.
Suppose that the ITER and COMBINE aggregate support functions for the SUMSQ aggregate are compiled and linked into a shared-object module named sumsq.
On UNIX or Linux, the executable code for the SUMSQ aggregate support functions would be in a shared library named sumsq.so.
CREATE FUNCTION iter_sumsq(state INTEGER, one_value INTEGER)
RETURNS INTEGER
WITH (HANDLESNULLS)
EXTERNAL NAME '/usr/udrs/aggs/sums/sumsq.so'
LANGUAGE C;
CREATE FUNCTION combine_sumsq(state1 INTEGER, state2 INTEGER)
RETURNS INTEGER
EXTERNAL NAME '/usr/udrs/aggs/sums/sumsq.so'
LANGUAGE C;
SELECT SUMSQ(col3) FROM tab1;
With the rows that Figure 1 has inserted, the preceding query yields an INTEGER value of 2173. To be able to use SUMSQ on other data types, you need to ensure that the appropriate aggregate support functions exist for this data type.