Thread: Re: [NOVICE] Functions in C with Ornate Data Structures

Re: [NOVICE] Functions in C with Ornate Data Structures

From
Tom Lane
Date:
"Stephen P. Berry" <spb@meshuggeneh.net> writes:
> If my data types were simpler, I could simply use an AGGREGATE function.
> Unfortunately, I don't know of any way to schlep something as complex
> as a doubly-linked list of arrays of arbitrary precision numbers.

You could, but the amount of data copying needed would be annoying.
However, there's no law that says you can't cheat.  I'd suggest that
you build this as an aggregate function whose nominal state value is
simply a pointer to data structures that are off somewhere else.

For example, assuming that you are willing to cheat to the extent of
assuming sizeof(pointer) = sizeof(integer), try something like this:

CREATE AGGREGATE crunch_number (
 basetype = float8,  -- or whatever the input column type is
 sfunc = crunch_func,
 stype = integer,
 ffunc = crunch_finish,
 initcond = 0);

where crunch_func(integer) returns integer is your data accumulation
function, and it looks like

    datstruct *ptr = (datstruct *) PG_GET_INT32(0);
    double newdataval = PG_GET_FLOAT8(1);

    if (ptr == NULL)
    {
        /* first call of query; initialize datastructures */
    }

    /* update datastructures using newdataval */

    PG_RETURN_INT32((int32) ptr);

Finally, crunch_finish(integer) returns float8 (or whatever is needed)
contains your code to compute the final result and release the working
datastructure.

Now, the important detail: you can't allocate your working
datastructures with a simple palloc(), because these functions will be
called in a short-lived memory context.  What I'd suggest is that in
your setup step, you create a private memory context that is a child
of TransactionCommandContext; then allocate all your datastructures in
that.  Then in the crunch_finish step, you needn't bother with retail
releasing of the data structures, just destroy the private context
and you're done.

            regards, tom lane

PS: this is not a novice-level question ;-).  You should be asking this
kind of stuff on pgsql-hackers, methinks.  There really isn't any other
list that discusses C coding inside the backend.