X-Original-To: pgsql-sql-postgresql.org@localhost.postgresql.org Received: from localhost (unknown [64.117.224.130]) by svr1.postgresql.org (Postfix) with ESMTP id BC639D1B4FF for ; Sun, 28 Sep 2003 20:05:43 +0000 (GMT) Received: from svr1.postgresql.org ([64.117.224.193]) by localhost (neptune.hub.org [64.117.224.130]) (amavisd-new, port 10024) with ESMTP id 12830-02 for ; Sun, 28 Sep 2003 17:05:35 -0300 (ADT) Received: from bast.unixathome.org (bast.unixathome.org [66.11.174.150]) by svr1.postgresql.org (Postfix) with ESMTP id C2B1ED1B503 for ; Sun, 28 Sep 2003 17:05:32 -0300 (ADT) Received: from wocker (wocker.unixathome.org [192.168.0.99]) by bast.unixathome.org (Postfix) with ESMTP id 040D53F52; Sun, 28 Sep 2003 16:05:13 -0400 (EDT) From: "Dan Langille" To: Tom Lane Date: Sun, 28 Sep 2003 16:06:20 -0400 MIME-Version: 1.0 Subject: Re: Cc: pgsql-sql@postgresql.org Message-ID: <3F7706FC.13057.3006C804@localhost> References: <20030928151910.S78282@laptop.unixathome.org> In-reply-to: <10801.1064778322@sss.pgh.pa.us> X-mailer: Pegasus Mail for Windows (v4.02a) Content-type: text/plain; charset=US-ASCII Content-transfer-encoding: 7BIT Content-description: Mail message body X-Virus-Scanned: by amavisd-new at postgresql.org X-Archive-Number: 200309/369 X-Sequence-Number: 15347 On 28 Sep 2003 at 15:45, Tom Lane wrote: > Dan Langille writes: > > WHERE lastlogin between current_date - interval \''' || > > quote_literal(i - 1) || '' days\' > > AND current_date - interval \''' || > > quote_literal(i) || '' days\'''; > > IIRC, quote_literal() puts single quotes around its result. So you have > too many quotes there. Given that you know i is an integer, you don't > really need quote_literal for it. Actually, you don't need EXECUTE > here at all. Why not just > > FOR i IN 1..MaxDays LOOP > SELECT count(*) > INTO r > FROM users > WHERE lastlogin between current_date - (i-1) * interval ''1 day'' > AND current_date - i * interval ''1 day''; > RETURN NEXT r; > END LOOP; Thank you. I had to replace the " with \', but here is what I came up with (after adding another item to the SELECT): CREATE OR REPLACE FUNCTION LoginCounts(int) RETURNS SETOF logincounts_record AS ' DECLARE MaxDays ALIAS for $1; r logincounts_record%rowtype; i integer; BEGIN raise notice ''MaxDays''; FOR i IN 1..MaxDays LOOP SELECT 1 AS days, count(*) as count INTO r FROM users WHERE lastlogin between current_date - (i-1) * interval \'1 day\' AND current_date - i * interval \'1 day\'; RETURN NEXT r; END LOOP; RETURN; END ' LANGUAGE plpgsql; However, the results are confusing. I'm getting the wrong number of parameters. The value being returned appears to be the value supplied. But the log results show an interesting pattern in the number of selects being run. working-copy.freshports.org=# select count(*) from LoginCounts(1); NOTICE: MaxDays count ------- 1 (1 row) The log says: 2003-09-28 16:01:54 [32813] LOG: query: select count(*) from LoginCounts(1); 2003-09-28 16:01:54 [32813] NOTICE: MaxDays 2003-09-28 16:01:54 [32813] LOG: query: select cast($1 as timestamp without time zone) - $2; working-copy.freshports.org=# select count(*) from LoginCounts(2); NOTICE: MaxDays count ------- 2 (1 row) And the log says: 2003-09-28 16:02:04 [32813] LOG: query: select count(*) from LoginCounts(2); 2003-09-28 16:02:04 [32813] NOTICE: MaxDays 2003-09-28 16:02:04 [32813] LOG: query: select cast($1 as timestamp without time zone) - $2; 2003-09-28 16:02:04 [32813] LOG: query: select cast($1 as timestamp without time zone) - $2; 2003-09-28 16:02:04 [32813] LOG: query: select cast($1 as timestamp without time zone) - $2; The type in question is: CREATE TYPE logincounts_record AS ( days integer, count integer ); -- Dan Langille : http://www.langille.org/