<div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">On Wed, Oct 15, 2014 at 6:16 PM, Lasse Makholm <span dir="ltr">&lt;<a href="mailto:lasse@unity3d.com" target="_blank">lasse@unity3d.com</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote"><span class="">On Wed, Oct 15, 2014 at 7:11 PM, Sean Quinlan <span dir="ltr">&lt;<a href="mailto:spq.easy@gmail.com" target="_blank">spq.easy@gmail.com</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir="ltr">Thanks!<div><br></div><div>I would have prefered to _not_ have to set unsafe, as it would be great if DBIC continued to handle exceptions internally as always, but just didn&#39;t pass the exception out after catching and handling it internally.<div><div><br></div><div>And I appreciate the &#39;<font face="arial, sans-serif"><span style="font-size:12.7272720336914px">architecturally unsound&#39; warning, and would agree in general. The only reason we&#39;re doing it this way is that we already have exception handling built in to the application. The idea here is not to just skip handling exceptions, but rather automate </span>propagating<span style="font-size:12.7272720336914px"> exceptions up to the application level, without having to hand-wrap all calls in eval. So if handle_error in DBI calls our applications add_error() (_without_ blocking or altering DBIC&#39;s), then the die on call is redundant, as the apps existing error handling will pick it up.</span></font></div></div></div></div></blockquote><div><br></div></span><div>I&#39;m really struggling to understand this reasoning, so forgive me if I come across as telling you that you&#39;re doing it all wrong...</div><div><br></div><div>Surely exceptions are always propagated up through the call stack to the nearest catch block and since DBIC does not catch exceptions for you, you are free to put a try/catch pair as high or as low in the call stack as you want. The whole point of structured exception handling is to let you put error handling where you want it instead of around every call that might possibly go wrong, no?</div></div></div></div></blockquote><div><br></div><div>Exactly!!!! My issue has been finding the right way to do that &quot;instead of around every call that might possibly go wrong&quot;! In straight DBI I would write a custom HandleError and set RaiseError to 0. Simple, done, I now control error handling. But I can&#39;t do that with DBIC.</div><div><br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><div><br></div><div>A try/catch pair in your dispatcher or entry point to your response handler should be a trivial thing to implement and would take care of meaningful responses in case of exceptions. Assuming no other try/catch pairs in the code path for a given request, that would still, of course, abort execution after the first error. But you want it to continue, right? Is that the crux of the matter?</div></div></div></div></blockquote><div><br></div><div>No, the crux of the matter is I _want_ something like:</div><div>    $row-&gt;update({col =&gt; &quot;value&quot;});</div><div>    return if $self-&gt;has_errors;</div><div><br></div><div>Rather than something like:</div><div>    eval {</div><div>        $row-&gt;update({col =&gt; &quot;value&quot;}); </div><div>    };</div><div>    if ($@) {</div><div>        $self-&gt;add_error(&quot;DB error stuffs&quot;);</div><div>        return;</div><div>    }</div><div><br></div><div>Where the if ($@) block is basically the same, repeated all over the place. Certainly we can just repeat that boiler plate over and over and over. But please, no. I do have a try/catch at the dispatch level of course, but that provides just a generic error (yes, with $@ in the details), as DBIC has effectively bypassed all of our internal error handling!</div><div> </div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><div><br></div><div>I guess you have your reasons wanting to do that but I can think of any number of reasons (ranging from simply returning incorrect data to deleting the wrong data or worse) why this approach is dangerous. And I guess that&#39;s what Peter means by &quot;<span style="font-family:arial,sans-serif;font-size:13px">architecturally unsound&quot;...</span></div></div></div></div></blockquote><div><br></div><div>Yes yes yes. But the point I seem to not be getting across is that I do NOT want to ignore errors. I just want to handle them the same way the rest of the application handles them. Sometimes we return right away, some times we need to do some other stuff after an error first. No matter what happens (even if a dev missed adding a return if or eval), the application examines $self-&gt;errors before finalizing the request and returning the response.</div><div><br></div><div>Again, no matter what, the first thing I need to make sure always happens is that $self-&gt;add_error(...) is called _before_ the application dies.</div><div> </div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><div><br></div><div>Given a chunk of code that does multiple inserts/updates - do you really want it to just blindly continue, even after something has gone wrong?<br></div></div></div></div></blockquote><div><br></div><div>Of course not! But I also don&#39;t want the error caught by an eval two levels higher, nor have to litter our code with repetitive evals for every operation. The goal here is to simplify the common cases and integrate DBIC with our application, rather than fight with it.</div><div> </div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><div></div><div><br></div><div>I&#39;m curious about what sort of application would want that kind of unsafe-by-default behaviour...</div></div></div></div></blockquote><div><br></div><div>&lt;sigh&gt;</div><div> </div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><span class=""><div> <br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir="ltr"><div><div><div><font face="arial, sans-serif"><span style="font-size:12.7272720336914px"></span></font></div><div><font face="arial, sans-serif"><span style="font-size:12.7272720336914px">Actually, if you wanted to encourage die or handle as an explicit decision and still discourage not handling it at all, perhaps a new optional argument to connect to provide a callback for external error handling, which when provided sets DBIC to not </span>propagate<span style="font-size:12.7272720336914px"> fatal errors to the application? exception_action seemed to come close, but was </span>triggered<span style="font-size:12.7272720336914px"> too often and did not suppress the die.</span></font></div></div></div></div></blockquote><div> </div></span><div>You probably know this already but in case you don&#39;t: With DBIC it&#39;s a relatively trivial thing to create your own base class for all resultsets and all result classes in your schema.</div></div></div></div></blockquote><div><br></div><div>I did not. I knew I could do that for every specific resultset (lots of examples of that). How do I override the base class for all resultsets in one place. Just create my own class with:</div><div>    use base &#39;DBIx::Class::Core&#39;;</div><div><br></div><div>And change all the Result classes to base from mine? But that then breaks dbicdump, which I would also like to avoid. Or is there a better way to do it that I missed in the docs?</div><div> </div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><div> In those two classes, overriding insert(), update() and a handful of other methods</div></div></div></div></blockquote><div><br></div><div>Which? Just add one for each method we end up using? Or should I just AUTOLOAD an override for all of them?</div><div> </div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><div> would probably get you what you want. It&#39;s of course more work than just flipping a switch in DBIC, but it&#39;s a lot less work than changing every place you call into DBIC. E.g. assuming a property on your schema that knows what to do with exceptions, something like:</div><div><br></div><div><div><div>sub update</div><div>{</div><div><span style="white-space:pre-wrap">        </span>my $self = shift;</div><div><span style="white-space:pre-wrap">        </span>return try {</div><div><span style="white-space:pre-wrap">                </span>$self-&gt;next::method(@_);</div><div><span style="white-space:pre-wrap">        </span>} catch {</div><div><span style="white-space:pre-wrap">                </span>$self-&gt;result_source-&gt;schema-&gt;some_context_thingy-&gt;add_error($_);</div><div><span style="white-space:pre-wrap">        </span>};</div><div>}</div></div></div><span class=""><font color="#888888"><div><br></div></font></span></div></div></div></blockquote></div><br></div><div class="gmail_extra">This sounds a little tougher than sending a callback to the initial connect method, as I&#39;d also have to find a way to get the enclosing application object passed into these override definitions. ... Or figure out how to pass in my own callback to be used there. But if you can guide me to the right place to insert my own subclass(es) in the chain without breaking things I can hopefully figure out how to pass what I need in.</div><div class="gmail_extra"><br></div><div class="gmail_extra">Much appreciated,</div><div class="gmail_extra">Sean</div></div>