Received: from localhost (unknown [200.46.204.183]) by postgresql.org (Postfix) with ESMTP id 73F652E003E for ; Fri, 15 Feb 2008 06:03:09 -0400 (AST) Received: from postgresql.org ([200.46.204.71]) by localhost (mx1.hub.org [200.46.204.183]) (amavisd-maia, port 10024) with ESMTP id 54443-01 for ; Fri, 15 Feb 2008 06:03:02 -0400 (AST) Received: from pih-relay08.plus.net (pih-relay08.plus.net [212.159.14.134]) by postgresql.org (Postfix) with ESMTP id 02F9D2E02AB for ; Fri, 15 Feb 2008 05:38:44 -0400 (AST) Received: from [84.51.143.99] (helo=server3.office.archonet.com) by pih-relay08.plus.net with esmtp (Exim) id 1JPx1l-00036j-Dw; Fri, 15 Feb 2008 09:38:41 +0000 Received: from [192.168.1.36] (dell36.office.archonet.com [192.168.1.36]) by server3.office.archonet.com (Postfix) with ESMTP id 302E327405A; Fri, 15 Feb 2008 09:38:41 +0000 (GMT) Message-ID: <47B55DA1.1060706@archonet.com> Date: Fri, 15 Feb 2008 09:38:41 +0000 From: Richard Huxton User-Agent: Thunderbird 2.0.0.9 (X11/20071031) MIME-Version: 1.0 To: "Dean Gibson (DB Administrator)" CC: pgsql-sql Subject: Re: FUNCTIONs and CASTs References: <47B4C9E4.8090002@ultimeth.com> <20670.1203031191@sss.pgh.pa.us> <47B4EF3E.4090608@ultimeth.com> In-Reply-To: <47B4EF3E.4090608@ultimeth.com> Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit X-Plusnet-Relay: b17e8f730cd13b174553a1d265e58b10 X-Virus-Scanned: Maia Mailguard 1.0.1 X-Archive-Number: 200802/116 X-Sequence-Number: 30207 Dean Gibson (DB Administrator) wrote: > On 2008-02-14 15:19, Tom Lane wrote: >> It's not exactly clear what you checked, but it works as expected for >> me. See test case below, proving that indexscan works just fine with >> a parameter declared using %type. > > Consider: > > CREATE TABLE zzz( aaa CHAR( 10 ) ); > > CREATE FUNCTION dummy( zzz.aaa%TYPE ) RETURNS zzz.aaa%TYPE > LANGUAGE SQL AS 'SELECT * FROM zzz WHERE CAST( $1 AS zzz.aaa%TYPE) = > aaa'; > > The notation "zzz.aaa%TYPE" fails when specified in the cast; it's fine > in the function prototype. However, specifying it in the function > prototype doesn't appear to help the performance issue: I get the same result: "works here". richardh=> CREATE TABLE zzz( aaa CHAR( 10 ) ); CREATE TABLE richardh=> INSERT INTO zzz SELECT generate_series(1,100000)::text; INSERT 0 100000 richardh=> CREATE INDEX zzz_aaa_idx ON zzz (aaa); CREATE INDEX richardh=> CREATE OR REPLACE FUNCTION dummy2( zzz.aaa%TYPE ) RETURNS zzz.aaa%TYPE richardh-> LANGUAGE SQL AS $$SELECT * FROM zzz WHERE aaa = $1 $$; NOTICE: type reference zzz.aaa%TYPE converted to character NOTICE: type reference zzz.aaa%TYPE converted to character CREATE FUNCTION Time: 15.268 ms richardh=> SELECT dummy2('99999'); dummy2 ------------ 99999 (1 row) Time: 1.962 ms richardh=> DROP INDEX zzz_aaa_idx; DROP INDEX richardh=> SELECT dummy2('99999'); dummy2 ------------ 99999 (1 row) Time: 45.418 ms What does this do on your machine? > Here is the actual function that caused be heartburn. The types in the > function prototype match EXACTLY the types of the actual parameters > being passed (and I also tried it with the tablename.columnname%TYPE > notation), and yet this function is slow. However, if I replace the > "$1" in the function body with "CAST( $1 AS CHAR( 10 ) )", the function > is very fast. Note that ALL of the column names in the function below > are indexed, so this function should be very fast (and is, with the CASTs). Hang on though - this function isn't using %TYPE, it's using explicit type definitions. If this function is slow, how can it be anything do with %TYPE ? > CREATE OR REPLACE FUNCTION "Functions".prior_call( CHAR( 10 ), > CHAR( 9 ), DATE) RETURNS BOOLEAN > STABLE RETURNS NULL ON NULL INPUT LANGUAGE SQL AS $SQL$ > SELECT COALESCE( (SELECT TRUE > FROM lic_hd > NATURAL JOIN lic_en > NATURAL JOIN lic_am > WHERE $1 = licensee_id > AND $2 > IN( callsign, prev_callsign ) > AND $3 > > grant_date > LIMIT 1), > (SELECT TRUE > FROM _preuls > WHERE $1 = licensee_id > AND $2 > IN( callsign, prev_callsign ) > LIMIT 1), > FALSE ) > $SQL$; > > So, I think you can see why it would be nice if the > tablename.columnname%TYPE notation could be used in the function body. Shouldn't be necessary (see above). > I'm not asking for that as an enhancement; rather, I'm trying to > understand what the tablename.columnname%TYPE notation accomplishes, > since specifying it in the function prototype doesn't appear to > accomplish anything (at least for me) over just specifying "TEXT". It specifies the type of the variable (or parameter) in question. The reason you can't use %TYPE directly in your SQL is because afaik it's not SQL - it's a PostgreSQL extension designed to specify variable types in functions. SQL constructs tend to expect a literal type name. I'm not sure what your problem is, but it's not the %TYPE operator, that's clear. Can you try reproducing the function as a prepared query? That way you can run EXPLAIN ANALYSE on it and see what's actually happening here. -- Richard Huxton Archonet Ltd