in reply to $sth = $dbh->prepare($sql) or what?
Couple of thoughts. First, in most of my programs lately you’ll find this. (Have a look at these Perl modules ...):
use Try::Tiny; use Exception::Class; use Exception::Caught; use except::classes; // the app-specific taxonomy of classes
In my code, there is a class which descends from a statement-handle and which incorporates this kind of specific error-checking into it, throwing an appropriate structured error object which might contain properties of its own. The checking of DBI return-codes and so-forth is used but it only occurs in one place. You don’t have to check if the statement succeeded because an exception (object...) will have been thrown if it didn’t.
In fact, the entire app is built around the principle of, “if you screw up, you won’t make it out of here alive.” Even user-errors cause exceptions to be thrown, to be caught if necessary at the highest levels of the program. Some logic catches one error, then re-throws another, in exception handling blocks that are built like the layers of an onion. The handling of exception cases, if you will, is now no longer “exceptional.” It has a very well defined path that is consistently followed. The nested class-hierarchy of error objects naturally provided by Exception::Class is used to good effect.
The outer-level logic contains a try block (which is syntactic sugar provided by Try::Tiny), which looks for these exception classes. If the logic succeeded, it makes it all the way through; if it doesn’t, it winds up in the catch-block, and in its catcher’s mitt comes an object of a particular recognizable class with particular and predictable properties. (If “a string” is caught instead, it’s known to be a bad-bug of some sort.)