A suggestion on PG_TRY() exception handling code. - Mailing list pgsql-hackers

From Gurjeet Singh
Subject A suggestion on PG_TRY() exception handling code.
Date
Msg-id 65937bea0611161350n5b55dcc6w18d0210e490817e8@mail.gmail.com
Whole thread Raw
Responses Re: A suggestion on PG_TRY() exception handling code.
List pgsql-hackers
Hi hackers,<br /><br />    The current usage PG_TRY() looks something like this:<br /><br /><span style="font-family:
couriernew,monospace;">    ... normal code ...<br /><br />    PG_TRY();</span><br style="font-family: courier
new,monospace;"/><span style="font-family: courier new,monospace;">    {</span><br style="font-family: courier
new,monospace;"/><span style="font-family: courier new,monospace;">        ... code that might throw ereport(ERROR)
...</span><brstyle="font-family: courier new,monospace;" /><span style="font-family: courier new,monospace;">   
}</span><brstyle="font-family: courier new,monospace;" /><span style="font-family: courier new,monospace;">   
PG_CATCH();</span><brstyle="font-family: courier new,monospace;" /><span style="font-family: courier
new,monospace;">   {</span><br style="font-family: courier new,monospace;" /><span style="font-family: courier
new,monospace;">       ... error recovery code ...</span><br style="font-family: courier new,monospace;" /><span
style="font-family:courier new,monospace;">        ... plus anything that you wish to do even if an error wasn't thrown
...</span><brstyle="font-family: courier new,monospace;" /><span style="font-family: courier new,monospace;">
           (because of a PG_RE_THROW possibility)</span><br style="font-family: courier new,monospace;" /><span
style="font-family:courier new,monospace;">    }</span><br style="font-family: courier new,monospace;" /><span
style="font-family:courier new,monospace;">     PG_END_TRY();<br /><br />    ... do the same thing over again; since
eitherno ERROR or no RE_THROW() ...<br /></span><br clear="all" /><span style="font-family: courier new,monospace;">   
...normal code ...<br /><br /></span>I propose a new constuct, PG_FINALLY. This will help in eliminating code
duplication(hence lesser possibility of errors), and better modularity. It will also help if someone wishes to call a
non-idempotentfunction in the now-repeating code. <br /><br /><span style="font-family: courier new,monospace;">#define
PG_TRY()                                                       \</span><br style="font-family: courier new,monospace;"
/><spanstyle="font-family: courier new,monospace;">     do
{                                                               \</span><br style="font-family: courier new,monospace;"
/><spanstyle="font-family: courier new,monospace;">        sigjmp_buf *save_exception_stack =
PG_exception_stack;         \ </span><br style="font-family: courier new,monospace;" /><span style="font-family:
couriernew,monospace;">        ErrorContextCallback *save_context_stack = error_context_stack; \</span><br
style="font-family:courier new,monospace;" /><span style="font-family: courier new,monospace;">        bool do_re_throw
=false;                                       \</span><br style="font-family: courier new,monospace;" /><span
style="font-family:courier new,monospace;">         sigjmp_buf local_sigjmp_buf;                                   
\</span><brstyle="font-family: courier new,monospace;" /><span style="font-family: courier new,monospace;">        if
(sigsetjmp(local_sigjmp_buf,0) == 0)                        \ </span><br style="font-family: courier new,monospace;"
/><spanstyle="font-family: courier new,monospace;">       
{                                                              \</span><br style="font-family: courier new,monospace;"
/><spanstyle="font-family: courier new,monospace;">            PG_exception_stack = &local_sigjmp_buf</span><br
style="font-family:courier new,monospace;" /><br style="font-family: courier new,monospace;" /><span
style="font-family:courier new,monospace;"> #define PG_CATCH()                                                     
\</span><brstyle="font-family: courier new,monospace;" /><span style="font-family: courier new,monospace;">       
}                                                              \ </span><br style="font-family: courier new,monospace;"
/><spanstyle="font-family: courier new,monospace;">       
else                                                           \</span><br style="font-family: courier new,monospace;"
/><spanstyle="font-family: courier new,monospace;">       
{                                                              \</span><br style="font-family: courier new,monospace;"
/><brstyle="font-family: courier new,monospace;" /><span style="font-family: courier new,monospace;">#define
PG_FINALLY()                                                   \</span><br style="font-family: courier new,monospace;"
/><spanstyle="font-family: courier new,monospace;">        
}                                                              \</span><br style="font-family: courier new,monospace;"
/><spanstyle="font-family: courier new,monospace;">       
{                                                              \ </span><br style="font-family: courier new,monospace;"
/><spanstyle="font-family: courier new,monospace;">            PG_exception_stack =
save_exception_stack;                 \</span><br style="font-family: courier new,monospace;" /><span
style="font-family:courier new,monospace;">            error_context_stack = save_context_stack</span><br
style="font-family:courier new,monospace;" /><br style="font-family: courier new,monospace;" /><span
style="font-family:courier new,monospace;"> #define PG_END_TRY()                                                   
\</span><brstyle="font-family: courier new,monospace;" /><span style="font-family: courier new,monospace;">       
}                                                              \ </span><br style="font-family: courier new,monospace;"
/><spanstyle="font-family: courier new,monospace;">        if
(do_re_throw)                                               \</span><br style="font-family: courier new,monospace;"
/><spanstyle="font-family: courier new,monospace;">            siglongjmp(*PG_exception_stack,
1)                         \</span><br style="font-family: courier new,monospace;" /><span style="font-family: courier
new,monospace;">    } while (0)</span><br style="font-family: courier new,monospace;" /><br style="font-family: courier
new,monospace;"/><span style="font-family: courier new,monospace;">#define PG_RE_THROW()   do_re_throw = true</span><br
style="font-family:courier new,monospace;" /><br />This would change the semantics to:<br /><br /><span
style="font-family:courier new,monospace;">    ... normal code ...<br /><br />     PG_TRY();</span><br
style="font-family:courier new,monospace;" /><span style="font-family: courier new,monospace;">    {</span><br
style="font-family:courier new,monospace;" /><span style="font-family: courier new,monospace;">        ... code that
mightthrow ereport(ERROR) ...</span><br style="font-family: courier new,monospace;" /><span style="font-family: courier
new,monospace;">   }</span><br style="font-family: courier new,monospace;" /><span style="font-family: courier
new,monospace;">   PG_CATCH();</span><br style="font-family: courier new,monospace;" /><span style="font-family:
couriernew,monospace;">    {</span><br style="font-family: courier new,monospace;" /><span style="font-family: courier
new,monospace;">       ... (optional) error recovery code only *and/or* RE_THROW...</span><br style="font-family:
couriernew,monospace;" /><span style="font-family: courier new,monospace;"></span><span style="font-family: courier
new,monospace;">   }</span><br style="font-family: courier new,monospace;" /><span style="font-family: courier
new,monospace;">   PG_FINALLY();</span><br style="font-family: courier new,monospace;" /><span style="font-family:
couriernew,monospace;">    {</span><br style="font-family: courier new,monospace;" /><span style="font-family: courier
new,monospace;">       ... do something that you wanted done in any case; ERROR or not ...</span><br
style="font-family:courier new,monospace;" /><span style="font-family: courier new,monospace;"></span><span
style="font-family:courier new,monospace;">    }</span><br style="font-family: courier new,monospace;" /><span
style="font-family:courier new,monospace;"></span><span style="font-family: courier new,monospace;">   
PG_END_TRY();<br/><br /></span><span style="font-family: courier new,monospace;">    ... normal code ...<br
/></span><br/>Hope to find buyers.<br /><br />Best regards,<br /><br />-- <br />gurjeet[.singh]@EnterpriseDB.com<br
/>singh.gurjeet@{gmail | hotmail | yahoo }.com  

pgsql-hackers by date:

Previous
From: "Gurjeet Singh"
Date:
Subject: Re: [GENERAL] Not your father's question about deadlocks
Next
From: Tom Lane
Date:
Subject: Re: A suggestion on PG_TRY() exception handling code.