Re: Error handling in plperl and pltcl - Mailing list pgsql-hackers

From Jan Wieck
Subject Re: Error handling in plperl and pltcl
Date
Msg-id 41AE9957.4070505@Yahoo.com
Whole thread Raw
In response to Re: Error handling in plperl and pltcl  (Brett Schwarz <brett_schwarz@yahoo.com>)
Responses Re: Error handling in plperl and pltcl
List pgsql-hackers
On 12/1/2004 1:35 PM, Brett Schwarz wrote:

> --- Jan Wieck <JanWieck@Yahoo.com> wrote:
> 
>> On 12/1/2004 9:23 AM, Jan Wieck wrote:
>> 
>> > On 12/1/2004 4:27 AM, Richard Huxton wrote:
>> > 
>> >> Thomas Hallgren wrote:
>> >>> Richard Huxton wrote:
>> >>> 
>> >>>> Can I make some counter-proposals?
>> >>>>
>> >>>> 1. Wrap each function body/call (same thing
>> here afaict) in a 
>> >>>> sub-transaction. An exception can be caught
>> within that function, and 
>> >>>> all the spi in that function is then rolled
>> back. This is rubbish, but 
>> >>>> at least it's predictable and allows you to
>> write to a log table and 
>> >>>> throw another exception.
>> >>> 
>> >>> 
>> >>> This will be even worse since it will impose the
>> subtransaction overhead 
>> >>> on everything, even functions that never do any
>> database access. Perhaps 
>> >>> this approach would be feasible if imposed on
>> volatile functions only, 
>> >>> but then again, the volatility of a function
>> cannot be trusted since we 
>> >>> have no way of defining a "stable but with side
>> effects" type.
>> >> 
>> >> Actually, I was thinking of setting a flag and
>> then on the first SPI 
>> >> call start the subtrans.
>> >> 
>> >>>> 2. For pl/tcl introduce a pgtry { } catch { }
>> which just starts a 
>> >>>> sub-transaction and does standard try/catch. I
>> don't use TCL, but from 
>> >>>> the little I know this should be
>> straightforward.
>> >>> 
>> >>> 
>> >>> If you know how to use special constructs like
>> this, what's wrong with 
>> >>> actually using savepoints verbatim? I.e.
>> >>> 
>> >>> INSERT 1
>> >>> INSERT 2
>> >>> SAVEPOINT foo
>> >>> try {
>> >>>  INSERT 3
>> >>>  INSERT 4
>> >>>  RELEASE foo
>> >>> }
>> >>> catch WHATEVER {
>> >>>  ROLLBACK TO foo
>> >>>  INSERT 5
>> >>>  INSERT 6
>> >>> }
>> >>> 
>> >>> IMHO a very clean, sensible, and easily
>> understood approach that doesn't 
>> >>> clobber the language.
>> >> 
>> >> But is the problem not that forgetting to use
>> SAVEPOINT can get us in 
>> >> trouble with clearing up after an exception?
>> That's the main thrust of 
>> >> Tom's per-statement stuff AFAICT. And again,
>> you're not going to see the 
>> >> problem until an exception is thrown.
>> > 
>> > I think the following would a) be a drop in
>> replacement without any side 
>> > effects or performance impact for PL/Tcl functions
>> not using "catch" and 
>> > b) give "catch" a sensible and correct behaviour.
>> > 
>> > One can _replace_ the Tcl catch command with his
>> own C function. This 
>> > can be done during the interpreter initialization
>> when loading the 
>> > PL/Tcl module. The new catch would
>> > 
>> >      push a status NEED_SUBTRANS onto a stack
>> >      call Tcl_Eval() for the first command
>> argument
>> >      if TCL_ERROR {
>> >          pop status from stack
>> >          if popped status == HAVE_SUBTRANS {
>> >              rollback subtransaction
>> >          }
>> >          if a second argument exists {
>> >              store interpreter result in variable
>> >          }
>> >          return TCL_ERROR
>> 
>> er ... no ... must return a true boolean with TCL_OK
>> here
>> 
>> >      }
>> >      pop status from stack
>> >      if popped status == HAVE_SUBTRANS {
>> >          commit subtransaction
>> >      }
>> > 
>> >      return result code from Tcl_Eval()
>> 
>> and here it must put a false boolean into the Tcl
>> result ... not 100% 
>> sure about the result code. Must check if it's
>> possible to return or 
>> break from inside a catch block ... if not, then
>> catch allways turns the 
>> internal result code into TCL_OK. Anyhow, you get
>> the idea.
>> 
> 
> Yes, you can have break, return in a catch
> statement...it would return the exception code for
> that statement (i.e. TCL_BREAK, TCL_RETURN).

Yeah ... little tests are nice :-)

catch allways returns the numeric Tcl result status, with TCL_OK being 
0, TCL_ERROR being 1 and so on.

> 
> I like this proposal, just as long as it behaves
> exactly like Tcl's catch when there is no SPI function
> call.

That's what I intended, plus that the catch-nesting automatically 
represents the subtransaction nesting. I can't really see any reason why 
those two should not be bound together. Does anybody?


Jan

-- 
#======================================================================#
# It's easier to get forgiveness for being wrong than for being right. #
# Let's break this rule - forgive me.                                  #
#================================================== JanWieck@Yahoo.com #


pgsql-hackers by date:

Previous
From: Michael Fuhr
Date:
Subject: Re: New compile warnings for inheritance
Next
From: Bruce Momjian
Date:
Subject: Re: Postresql 8.0 Beta 3 - SELECT ... FOR UPDATE