Обсуждение: AFTER triggers & RETURN
Tom's recent work to fix the (TG_OP = 'INSERT' and NEW.foo ...) problem reminded me of another PL/pgsql annoyance: create table foo (a integer); create or replace function broken() returns trigger as $$begin perform 1; end$$ language plpgsql; create trigger bar after insert on foo for each row execute procedure broken(); insert into foo values (1); ERROR: control reached end of trigger procedure without RETURN CONTEXT: PL/pgSQL function "broken" Since the return value is ignored anyway, why do we have to complain if it's left out altogether? Granted, it's easy to work around, but still. ...Robert
Robert Haas wrote: > Tom's recent work to fix the (TG_OP = 'INSERT' and NEW.foo ...) > problem reminded me of another PL/pgsql annoyance: > > create table foo (a integer); > create or replace function broken() returns trigger as $$begin perform > 1; end$$ language plpgsql; > create trigger bar after insert on foo for each row execute procedure broken(); > insert into foo values (1); > ERROR: control reached end of trigger procedure without RETURN > CONTEXT: PL/pgSQL function "broken" > > Since the return value is ignored anyway, why do we have to complain > if it's left out altogether? Granted, it's easy to work around, but > still. > > Isn't is a requirement of plpgsql that you not fall off the end of a function unless it is declared to return void? The function doesn't know if it will be called before or after. cheers andrew
Andrew Dunstan <andrew@dunslane.net> writes: > Robert Haas wrote: >> Since the return value is ignored anyway, why do we have to complain >> if it's left out altogether? Granted, it's easy to work around, but >> still. > Isn't is a requirement of plpgsql that you not fall off the end of a > function unless it is declared to return void? The function doesn't know > if it will be called before or after. Yeah, it couldn't be done as a compile-time check. You could probably make it work if you converted the error to a run-time test. Not sure if that's really an improvement though. regards, tom lane
On Thu, Nov 5, 2009 at 4:57 PM, Tom Lane <tgl@sss.pgh.pa.us> wrote: > Andrew Dunstan <andrew@dunslane.net> writes: >> Robert Haas wrote: >>> Since the return value is ignored anyway, why do we have to complain >>> if it's left out altogether? Granted, it's easy to work around, but >>> still. > >> Isn't is a requirement of plpgsql that you not fall off the end of a >> function unless it is declared to return void? The function doesn't know >> if it will be called before or after. > > Yeah, it couldn't be done as a compile-time check. You could probably > make it work if you converted the error to a run-time test. Not sure > if that's really an improvement though. Well, as it is, you don't get an error when you define the function, only when you do something that causes it to be invoked. An error when you define the function would probably be a small improvement, because at least it would be obvious that you'd broke something (and the transaction that tried to break it would roll back). No error at all seems better still. Perhaps in an ideal world before and after trigger functions would have different signatures - like the before trigger should perhaps take two rows as arguments and return a row, and the after trigger should take two rows as arguments and return void. The idea of overloading the function's return type to provide it with special, magical input parameters is pretty funky and means that you can't invoke that function in any context other than as a trigger, which would occasionally be useful. I think we're stuck with it at this point, but maybe it's possible to at least relax the requirement to explicitly return a useless result. ...Robert
On 11/5/2009 8:10 PM, Robert Haas wrote: > On Thu, Nov 5, 2009 at 4:57 PM, Tom Lane <tgl@sss.pgh.pa.us> wrote: >> Andrew Dunstan <andrew@dunslane.net> writes: >>> Robert Haas wrote: >>>> Since the return value is ignored anyway, why do we have to complain >>>> if it's left out altogether? Granted, it's easy to work around, but >>>> still. >> >>> Isn't is a requirement of plpgsql that you not fall off the end of a >>> function unless it is declared to return void? The function doesn't know >>> if it will be called before or after. >> >> Yeah, it couldn't be done as a compile-time check. You could probably >> make it work if you converted the error to a run-time test. Not sure >> if that's really an improvement though. > > Well, as it is, you don't get an error when you define the function, > only when you do something that causes it to be invoked. An error > when you define the function would probably be a small improvement, > because at least it would be obvious that you'd broke something (and > the transaction that tried to break it would roll back). No error at > all seems better still. > > Perhaps in an ideal world before and after trigger functions would > have different signatures - like the before trigger should perhaps > take two rows as arguments and return a row, and the after trigger > should take two rows as arguments and return void. The idea of > overloading the function's return type to provide it with special, > magical input parameters is pretty funky and means that you can't > invoke that function in any context other than as a trigger, which > would occasionally be useful. I think we're stuck with it at this > point, but maybe it's possible to at least relax the requirement to > explicitly return a useless result. One could of course have triggers return NEW by default for invocations on INSERT or UPDATE, and OLD on DELETE. That would make the default behavior of BEFORE triggers to let the original operation through and fix the annoyance. Jan -- Anyone who trades liberty for security deserves neither liberty nor security. -- Benjamin Franklin