On Wed, Mar 28, 2012 at 1:52 PM, Kenneth Tilton <ktilton@xxxxxxxx> 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
-ktOn Wed, Mar 28, 2012 at 12:54 PM, Kenneth Tilton <ktilton@xxxxxxxx> 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-bitI 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 statementNOTICE: 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 statementERROR: 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: 22007Context: PL/pgSQL function "bp_alert_init" line 7 at SQL statementNote 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 statementNOTICE: 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 statementNOTICE: 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 RAISESo 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$declarebeginraise 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$declarebpa bp_alert; -- make this a record and the "warn time in caller" raise fails on bpa not having warn_timebegin-- 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_alertBEFORE INSERTON bp_alertFOR EACH ROWEXECUTE PROCEDURE bp_alert_init();insert into bp_alert (warn_time_init) values ('now_plus_30');