On Wed, Mar 28, 2012 at 1:52 PM, Kenneth Tilton <ktil...@mcna.net> wrote:

> First, apologies for being too succinct. I should have reiterated the
> message subject to provide the context: I am just trying to return a row
> from a function and have the caller understand it. Oh, and I am a nooby so
> it is probably something daft.
>
> Second, I just tried returning the row as an out variable and got the same
> result. I'll try messing with the caller...
>

OK, this works in re getting the row back:

    bpa := now_plus_30(NEW);

But I need to execute an arbitrary function passed in as text, and I now
realize EXECUTE is for SQL and I am trying to use it to "eval" plpgsql and
those are different animals.

I see no plpgsql equivalent of EXECUTE, ie where I can build up a plpgsql
statement like this:

   execute 'bpa := ' || function_name || '($1)' using NEW into bpa;

Ideas welcome.

--kt


>
> -kt
>
>
> On Wed, Mar 28, 2012 at 12:54 PM, Kenneth Tilton <ktil...@mcna.net> wrote:
>
>> On version:
>>
>>     PostgreSQL 9.1.2 on x86_64-unknown-linux-gnu, compiled by gcc (GCC)
>> 4.4.5 20110214 (Red Hat 4.4.5-6), 64-bit
>>
>> I get this error (all code at end of post) in pgAdmin:
>>
>> NOTICE:  bpa inbound (,now_plus_30)
>>>
>>> CONTEXT:  SQL statement "select now_plus_30(NEW)"
>>>
>>> PL/pgSQL function "bp_alert_init" line 7 at SQL statement
>>>
>>> NOTICE:  warn time in input row = ("2012-04-27
>>>> 16:41:20.338239+00",now_plus_30)
>>>
>>> CONTEXT:  SQL statement "select now_plus_30(NEW)"
>>>
>>> PL/pgSQL function "bp_alert_init" line 7 at SQL statement
>>>
>>>
>>>>
>>>> ERROR:  invalid input syntax for type timestamp with time zone:
>>>> "("2012-04-27 16:41:20.338239+00",now_plus_30)"
>>>
>>> CONTEXT:  PL/pgSQL function "bp_alert_init" line 7 at SQL statement
>>>
>>>
>>>> ********** Error **********
>>>
>>>
>>>> ERROR: invalid input syntax for type timestamp with time zone:
>>>> "("2012-04-27 16:41:20.338239+00",now_plus_30)"
>>>
>>> SQL state: 22007
>>>
>>> Context: PL/pgSQL function "bp_alert_init" line 7 at SQL statement
>>>
>>>
>>>>
>> Note that I have eliminated the complexity of the callback and simply
>> call the desired initializer directly. FWIW, using the desired EXECUTE
>> statement produces exactly the same error.
>>
>> If I declare the receiving variable to be a record, pgAdmin shows me this:
>>
>> NOTICE:  bpa inbound (,now_plus_30)
>>>
>>> CONTEXT:  SQL statement "select now_plus_30(NEW)"
>>>
>>> PL/pgSQL function "bp_alert_init" line 7 at SQL statement
>>>
>>> NOTICE:  warn time in input row = ("2012-04-27
>>>> 16:46:22.62478+00",now_plus_30)
>>>
>>> CONTEXT:  SQL statement "select now_plus_30(NEW)"
>>>
>>> PL/pgSQL function "bp_alert_init" line 7 at SQL statement
>>>
>>> NOTICE:  caller got bpa ("(""2012-04-27
>>>> 16:46:22.62478+00"",now_plus_30)") <-----------------
>>>
>>>
>>>>
>>>> ERROR:  record "bpa" has no field "warn_time"
>>>
>>> CONTEXT:  SQL statement "SELECT bpa.warn_time"
>>>
>>> PL/pgSQL function "bp_alert_init" line 9 at RAISE
>>>
>>>
>> So it looks as if I have to "unwrap" or eval the return value (or change
>> the way I am returning it). But the callee is declared as returning a
>> bp_alert and returns a variable of type bp_alert, so I am not sure what
>> more I can do in the callee. The caller is selecting into a variable of
>> type bp_alert, so that too seems clear.
>>
>> Hints welcome, code next.
>>
>> ken
>>
>> -- code starts here
>> -------------------------------------------------------
>>
>> set search_path to public;
>> drop table if exists bp_alert cascade;
>>
>> CREATE TABLE bp_alert (
>>   warn_time          timestamp WITH TIME ZONE,
>>   warn_time_init     text
>> )
>>
>> CREATE OR REPLACE FUNCTION now_plus_30(bpa bp_alert)
>>   RETURNS bp_alert AS
>> $BODY$
>>
>> declare
>> begin
>>    raise notice 'bpa inbound %', bpa;
>>    bpa.warn_time = now() + interval '30 days';
>>    raise notice 'warn time in input row = %', bpa;
>>    return bpa;
>> end;
>> $BODY$
>>   LANGUAGE plpgsql VOLATILE;
>>
>> CREATE OR REPLACE FUNCTION bp_alert_init()
>>   RETURNS trigger AS
>> $BODY$
>>
>> declare
>>    bpa bp_alert; -- make this a record and the "warn time in caller"
>> raise fails on bpa not having warn_time
>> begin
>>    -- no difference: execute 'select ' || NEW.warn_time_init || '($1)'
>> using NEW into bpa;
>>    select now_plus_30(NEW) into bpa;
>>    raise notice 'caller got bpa %', bpa;
>>    raise notice 'warn time in caller now %', bpa.warn_time;
>>    return bpa;
>> end;
>> $BODY$
>>   LANGUAGE plpgsql VOLATILE;
>>
>> drop trigger if exists bp_alert on bp_alert;
>>
>> CREATE TRIGGER bp_alert
>>   BEFORE INSERT
>>   ON bp_alert
>>   FOR EACH ROW
>>   EXECUTE PROCEDURE bp_alert_init();
>>
>> insert into bp_alert (warn_time_init) values ('now_plus_30');
>>
>>
>

Reply via email to