On Fri, Sep 24, 2010 at 11:15 PM, Robert Haas <robertmh...@gmail.com> wrote:
> On Fri, Sep 24, 2010 at 3:41 PM, Tom Lane <t...@sss.pgh.pa.us> wrote: > > Robert Haas <robertmh...@gmail.com> writes: > >> On Tue, Sep 21, 2010 at 7:05 PM, Tom Lane <t...@sss.pgh.pa.us> wrote: > >>> There are many rules that you could possibly make for type input > >>> functions. But "you cannot throw an error" is not one of them --- > >>> or at least, not one that you can usefully expect to be followed > >>> for anything more than trivial straightline code. > > > >> OK. This is one of the things I don't understand. Why does throwing > >> an error imply that we need to abort the current transaction? Why > >> can't we just catch the longjmp() and trundle onwards? Obviously, > >> that's unsafe if a pretty wide variety of cases, but if you're just > >> scrutinizing the input string (even with a little bit of read-only > >> database access) it's not obvious to me what can go wrong. > > > > The problem is to know that "all you did" was scrutinize the input > > string. If it's simple straightline code (even with some C library > > calls) then you can know that, but then you can write such code without > > including any elog(ERROR) in it in the first place. If you are trapping > > longjmps then what you'd need to assert is that no error thrown from > > anywhere in any of the code reachable from that place represents a > > problem that requires transaction abort to clean up after. This gets > > unmaintainable remarkably quickly, especially if you invoke anything > > as complicated as database access. And then there are asynchronous > > error reasons (query cancel) which you shouldn't trap in any case. > > Hmm. So the problem is that we don't want to accidentally catch an > error that isn't actually safe to catch. We could probably mitigate > this problem to a considerable degree by throwing data validation > errors using some special flag that say "this is a recoverable error". > And if that flag isn't set then we abort the whole transaction, but > if it is then we continue on. It's still possible for the person > writing the typinput function to set that flag when they should not, > but at least it's less likely to happen by accident. Another > alternative would be to create some kind of explicit way for the > function to RETURN an error instead of throwing it. > > But neither of these things is totally bullet-proof, because you could > still do something that requires clean-up and then lie about it. To > protect against that, you'd presumably need to set some kind of a flag > whenever, say, a heap tuple gets modified, and then you could assert > said flag false. What, other than writing to the database, requires > subtransaction cleanup? > > Andrew suggested upthread: <snip> test_date := date_in(textout(some_text)); In plpgsql you'd put that inside a begin/exception/end block that traps SQLSTATE '22000' which is the class covering data exceptions. </snip> In context of COPY, can we check for this SQLSTATE in PG_CATCH() and avoid PG_RE_THROW(). This would require that all type input functions call errcode() with proper MAKE_SQLSTATE() as part of ereport()/elog(). Regards, -- gurjeet.singh @ EnterpriseDB - The Enterprise Postgres Company http://www.EnterpriseDB.com singh.gurj...@{ gmail | yahoo }.com Twitter/Skype: singh_gurjeet Mail sent from my BlackLaptop device