Re: [HACKERS] Aggregates with context - a question

Поиск
Список
Период
Сортировка
От Tom Lane
Тема Re: [HACKERS] Aggregates with context - a question
Дата
Msg-id 28779.928938007@sss.pgh.pa.us
обсуждение исходный текст
Ответ на Aggregates with context - a question  (Philip Warner <pjw@rhyme.com.au>)
Ответы Re: [HACKERS] Aggregates with context - a question  (Philip Warner <pjw@rhyme.com.au>)
Re: [HACKERS] Aggregates with context - a question  (Philip Warner <pjw@rhyme.com.au>)
Список pgsql-hackers
Philip Warner <pjw@rhyme.com.au> writes:
> The problems is that the way I read the code, there is an expectation
> that the parameters of sfuncX and finalfunc match the basetype.

No, not at all.  transfn1 has the signaturetranstype1 = transfn1 (transtype1, basetype)
ie, you take the state object and the next input value, and deliver a
new state object.  transfn2 has the signaturetranstype2 = transfn2 (transtype2)
ie, it operates on the second state object and delivers a new value.
And finalfn has the signaturefinaltype = finalfn (transtype1, transtype2)
ie, take the two state objects and deliver the desired result.
(You can also use a finalfn that takes only one state object,
if you are only using one transfn.)

If you omit finalfn then you can only supply one transfn, and the
corresponding transtype must equal finaltype because the default
behavior is just to copy the state value computed by the transfn
that's present.  But as long as you have a finalfn, all four datatypes
can be different.

This undoubtedly seems overly baroque, and it is overkill when writing
a specialized transfn from scratch; there's no need for transfn2, just
a transfn1 and a finalfn to produce the end result.  The reason it was
done this way (I assume; I wasn't there) is that you can produce many
useful aggregates by combining *existing* operators without having to
write any code at all.  For example, avg() for float8 is built from
transfn1 = float8pl, transfn2 = float8inc, and finalfn = float8div.

I am not sure whether this is adequately documented; probably not.
Will revisit the docs for 6.6 (I suppose Thomas will have my head
if I change 'em now ;-)).

> This is clearly not the case, and I have declared them as int4, which
> will also presumable break on 64 bit implementations...

The "clean" way to do it is to make a declared datatype that corresponds
to the state storage you need, but that's overkill if such a datatype
hasn't got any other use.  I think the way you have done it is a
reasonable cheat, though I agree that using int4 is risky for
portability.  There has been some talk of inventing a type OID
representing "C string", and that (when available) might be a better way
of declaring transtype1 when it's really a private struct of some sort.

One thing you have to be very careful about is memory allocation and
lifetime.  The way you are doing it, a palloc in the first transfn1
iteration and a pfree in finalfn, will be fine.  However this may change
in 6.6, since we are going to have to do something to cure memory leaks
in aggregation.  (Currently, if the transfns are ones that palloc their
result value, as all float8 ops do for example, the storage is not
reclaimed until end of transaction.  That's no good if there are lots of
tuples...)

> Anyway, the code is below.

Looks OK except you are potentially pfreeing an uninit pointer in the
finalfn...
        regards, tom lane


В списке pgsql-hackers по дате отправления:

Предыдущее
От: Daniel Kalchev
Дата:
Сообщение: Re: [HACKERS] Postgres 6.5 beta2 and beta3 problem
Следующее
От: Tom Lane
Дата:
Сообщение: Re: [HACKERS] Postgres 6.5 beta2 and beta3 problem