Thread: Return Record

Return Record

From
Rory Campbell-Lange
Date:
I'm not clear on how to handle returning a record from a function.
I have planned a function that is handed two strings and returns two
integers. I need to return errors that satisfy the return type. At the
moment my "RETURN 0;" lines result in "return type mismatch..." errors.

Thanks for any help.
Rory

/*
    ------------------------
    SQL FUNCTION FOR
    POSTGRES 7.3
    ------------------------
    Function name:         . fn_b1_login.sql
    Function description:  . Given an email address and password
                             return the person id and personal board id.
                             Also perform fn_e30_board_hide to turn on
                             persons profile (person object) by making
                             it unhidden if necessary.
*/

CREATE OR REPLACE FUNCTION fn_b1_login2
    (varchar, varchar) RETURNS record
    AS'
DECLARE
    email         ALIAS for $1;
    pass          ALIAS for $2;
    recone        RECORD;
BEGIN

    -- more extensive checking to be done in client program

    IF email IS NULL THEN
        RAISE EXCEPTION ''no email found at fn_e3_person_register'';
        RETURN (0, 0);
    END IF;

    IF pass IS NULL THEN
        RAISE EXCEPTION ''no pass found at fn_e3_person_register'';
        RETURN 0;
    END IF;

    --

    SELECT INTO recone
        p.n_id as nid, b.n_id as bid
    FROM
        people p, boards b
    WHERE
        p.t_email = email
        AND
        p.t_password = pass
        AND
        p.n_id = b.n_creator
        AND
        b.n_type = 0;

    IF NOT FOUND THEN
        RAISE EXCEPTION ''no person board combination found at fn_e3_person_register'';
        RETURN 0;
    END IF;

    RETURN recone;

END;'
    LANGUAGE plpgsql;


--
Rory Campbell-Lange
<rory@campbell-lange.net>
<www.campbell-lange.net>

Re: Return Record

From
Rory Campbell-Lange
Date:
On 06/06/03, Rory Campbell-Lange (rory@campbell-lange.net) wrote:
> I'm not clear on how to handle returning a record from a function.
> I have planned a function that is handed two strings and returns two
> integers. I need to return errors that satisfy the return type. At the
> moment my "RETURN 0;" lines result in "return type mismatch..." errors.

I've found a userful resource on postgresql.org:

"PostgreSQL 7.3 Set Returning Functions":
http://techdocs.postgresql.org/guides/SetReturningFunctions

However I'm still having trouble living up to the title of the article!

The error I'm getting is:
temporary=> select fn_b1_login('email@email', 'pass');
WARNING:  Error occurred while executing PL/pgSQL function fn_b1_login
WARNING:  while casting return value to function's return type
ERROR:  Set-valued function called in context that cannot accept a set



/*
    ------------------------
    SQL FUNCTION FOR
    POSTGRES 7.3
    ------------------------
    Function name:         . fn_b1_login.sql
    Function description:  . Given a persons email address and password
                             return the person id and personal board id.
                             Also perform fn_e30_board_hide to turn on
                             persons profile (person object) by making
                             it unhidden if necessary.
    ------------------------
    CVS                    . $Id: fn_b1_login.sql,v 1.2 2003/06/02 11:24:29 rory Exp $
    ------------------------
*/

DROP TYPE loginrec CASCADE;
CREATE TYPE loginrec as (nid INTEGER, bid INTEGER);

CREATE OR REPLACE FUNCTION fn_b1_login
    (varchar, varchar) RETURNS setof loginrec
    AS'
DECLARE
    email         ALIAS for $1;
    pass          ALIAS for $2;
    recone        RECORD;
    resulter      loginrec%rowtype;
BEGIN

    -- more extensive checking to be done in client program

    IF email IS NULL THEN
        RAISE EXCEPTION ''no email found at fn_e3_person_register'';
        -- RETURN (0, 0);
    END IF;

    IF pass IS NULL THEN
        RAISE EXCEPTION ''no pass found at fn_e3_person_register'';
        -- RETURN 0;
    END IF;

    --

    SELECT INTO recone
        p.n_id as nid, b.n_id as bid
    FROM
        people p, boards b
    WHERE
        p.t_email = email
        AND
        p.t_password = pass
        AND
        p.n_id = b.n_creator
        AND
        b.n_type = 0;

    IF NOT FOUND THEN
        RAISE EXCEPTION ''no person board combination found at fn_e3_person_register'';
    END IF;

    resulter.nid := recone.nid;
    resulter.bid := recone.bid;

    RETURN;

END;'
    LANGUAGE plpgsql;
--
Rory Campbell-Lange
<rory@campbell-lange.net>
<www.campbell-lange.net>

Re: Return Record

From
Antti Haapala
Date:
On Fri, 6 Jun 2003, Rory Campbell-Lange wrote:

> On 06/06/03, Rory Campbell-Lange (rory@campbell-lange.net) wrote:
> > I'm not clear on how to handle returning a record from a function.
> > I have planned a function that is handed two strings and returns two
> > integers. I need to return errors that satisfy the return type. At the
> > moment my "RETURN 0;" lines result in "return type mismatch..." errors.
>
> I've found a userful resource on postgresql.org:
>
> "PostgreSQL 7.3 Set Returning Functions":
> http://techdocs.postgresql.org/guides/SetReturningFunctions
>
> However I'm still having trouble living up to the title of the article!
>
> The error I'm getting is:
> temporary=> select fn_b1_login('email@email', 'pass');
> WARNING:  Error occurred while executing PL/pgSQL function fn_b1_login
> WARNING:  while casting return value to function's return type
> ERROR:  Set-valued function called in context that cannot accept a set

*sigh*

temporary=> select * from fn_b1_login('email@email', 'pass');

--
Antti Haapala

Re: Return Record

From
Joe Conway
Date:
Rory Campbell-Lange wrote:
> I'm not clear on how to handle returning a record from a function.
> I have planned a function that is handed two strings and returns two
> integers. I need to return errors that satisfy the return type. At the
> moment my "RETURN 0;" lines result in "return type mismatch..." errors.
>

You can't return type "record" in the ways you were trying (RETURN (0,
0); and RETURN 0;). Also, since you were raising EXCEPTION instead of
NOTICE, the function would never return anyway. See below -- I think it
does what you want:

CREATE OR REPLACE FUNCTION fn_b1_login2(varchar, varchar)
RETURNS record AS'
DECLARE
   email         ALIAS for $1;
   pass          ALIAS for $2;
   recone        RECORD;
BEGIN
   -- more extensive checking to be done in client program
   IF email IS NULL THEN
       RAISE NOTICE ''no email found at fn_e3_person_register'';
       SELECT into recone 0,0;
       RETURN recone;
   END IF;

   IF pass IS NULL THEN
       RAISE NOTICE ''no pass found at fn_e3_person_register'';
       SELECT into recone 0,0;
       RETURN recone;
   END IF;

   --
   SELECT INTO recone 1,2;
--      p.n_id as nid, b.n_id as bid
--  FROM
--      people p, boards b
--  WHERE
--      p.t_email = email
--      AND
--      p.t_password = pass
--      AND
--      p.n_id = b.n_creator
--      AND
--      b.n_type = 0;

   IF NOT FOUND THEN
       RAISE NOTICE ''no person board combination found at
fn_e3_person_register'';
       SELECT into recone 0,0;
       RETURN recone;
   END IF;

   RETURN recone;
END;
' LANGUAGE 'plpgsql';

regression=# select * from fn_b1_login2('a', null) as (pid int, bid int);
NOTICE:  no pass found at fn_e3_person_register
  pid | bid
-----+-----
    0 |   0
(1 row)

regression=# select * from fn_b1_login2(null, 'b') as (pid int, bid int);
NOTICE:  no email found at fn_e3_person_register
  pid | bid
-----+-----
    0 |   0
(1 row)

regression=# select * from fn_b1_login2('a', 'b') as (pid int, bid int);
  pid | bid
-----+-----
    1 |   2
(1 row)

HTH,
Joe




Re: Return Record

From
Richard Huxton
Date:
On Friday 06 Jun 2003 4:20 pm, Rory Campbell-Lange wrote:
> I'm not clear on how to handle returning a record from a function.
> I have planned a function that is handed two strings and returns two
> integers. I need to return errors that satisfy the return type. At the
> moment my "RETURN 0;" lines result in "return type mismatch..." errors.

> CREATE OR REPLACE FUNCTION fn_b1_login2
>     (varchar, varchar) RETURNS record
...
>     IF email IS NULL THEN
>         RAISE EXCEPTION ''no email found at fn_e3_person_register'';
>         RETURN (0, 0);
>     END IF;
...
>     RETURN recone;


OK - I think what you probably want to do is define a new type login_results
(CREATE TYPE login_results (n_id int, bid int)) and return that rather than
"record".

Then, I'd just set both fields of "recone" to null and return that during
error checks. It doesn't really matter what values you use since the
exception will kill the transaction anyway, but null seems better than 0.

--
  Richard Huxton