X-Original-To: pgsql-performance-postgresql.org@postgresql.org Received: from localhost (mx1.hub.org [200.46.208.251]) by postgresql.org (Postfix) with ESMTP id 7D3049FA5DD for ; Sun, 11 Jun 2006 14:19:30 -0300 (ADT) Received: from postgresql.org ([200.46.204.71]) by localhost (mx1.hub.org [200.46.208.251]) (amavisd-new, port 10024) with ESMTP id 17246-09 for ; Sun, 11 Jun 2006 14:19:25 -0300 (ADT) X-Greylist: from auto-whitelisted by SQLgrey- Received: from moonunit2.moonview.localnet (wsip-70-167-125-69.sd.sd.cox.net [70.167.125.69]) by postgresql.org (Postfix) with ESMTP id 36CD89FA3D7 for ; Sun, 11 Jun 2006 14:19:24 -0300 (ADT) Received: from [192.168.0.3] (moonunit3.moonview.localnet [192.168.0.3]) by moonunit2.moonview.localnet (8.13.1/8.13.1) with ESMTP id k5BHUvOI016869 for ; Sun, 11 Jun 2006 10:30:58 -0700 Message-ID: <448C505C.2080504@modgraph-usa.com> Date: Sun, 11 Jun 2006 10:18:20 -0700 From: "Craig A. James" User-Agent: Mozilla Thunderbird 1.0.6 (X11/20050716) X-Accept-Language: en-us, en MIME-Version: 1.0 To: pgsql-performance@postgresql.org Subject: function not called if part of aggregate Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit X-Virus-Scanned: Maia Mailguard 1.0.1 X-Archive-Number: 200606/117 X-Sequence-Number: 19474 My application has a function, call it "foo()", that requires initialization from a table of about 800 values. Rather than build these values into the C code, it seemed like a good idea to put them on a PG table and create a second function, call it "foo_init()", which is called for each value, like this: select foo_init(value) from foo_init_table order by value_id; This works well, but it requires me to actually retrieve the function's value 800 times. So I thought I'd be clever: select count(1) from (select foo_init(value) from foo_init_table order by value_id) as foo; And indeed, it count() returns 800, as expected. But my function foo_init() never gets called! Apparently the optimizer figures out that foo_init() must return one value for each row, so it doesn't bother to actually call the function. db=> explain select count(1) from (select foo_init(value) from foo_init_table order by db_no) as foo; query plan ---------------------------------------------------------------------------------------------------- aggregate (cost=69.95..69.95 rows=1 width=0) -> Subquery Scan foo (cost=0.00..67.93 rows=806 width=0) -> Index Scan using foo_init_table_pkey on foo_init_table (cost=0.00..59.87 rows=806 width=30) This doesn't seem right to me -- how can the optimizer possibly know that a function doesn't have a side effect, as in my case? Functions could do all sorts of things, such as logging activity, filling in other tables, etc, etc. Am I missing something here? Thanks, Craig