On Wed, Mar 31, 2004 at 08:23:02PM -0800, Michael Peppler wrote:
> On Wed, 2004-03-31 at 17:56, Jonathan Leffler wrote:
> > Dean Arnold wrote:
> > >>A few months ago we had discussed on this list _standardizing_ error
> > >>handling for things like trying to insert duplicate records, but I kind
> > >>of dropped the ball - changing jobs and all didn't leave me enough time
> > >>to persue that standardization with members of this list.  And since now
> > >>I don't use Perl in my new job, I don't have time to persue it at all. 
> > >>Anyone else have time to revisit standardizing error handling for things
> > >>like "Trying to insert duplicate record"???  Basically all it involved
> > >>was putting together a list of common error conditions and finding the
> > >>corresponding ODBC error codes.

Note that all I was after as a fairly *short* list of the specific SQLSTATE
codes that correspond to errors that applications *often* want to explicitly
check for. Duplicate key being an obvious example.

> > > Er, isn't that what $h->state() is for ? In *theory*, state (aka SQLSTATE)
> > > codes should be fairly uniform across DBMS's (tho there's always a
> > > lot of platform specific state codes as well).

Yes. There are two things I want to do:

1. Specify a fairly short list of the specific SQLSTATE values that
   I'd like drivers to support as a minimum.

2. Provide a simple way for drivers to map some of their private
   err values into the corresponding SQLSTATE values.
   Something like: $drh->{SQLSTATE_map} = $hash_ref_or_code_ref;
   The DBI would then use that to set state() if it was left undef.

All the driver would need to do is:

   $drh->{SQLSTATE_map} = {
        NNN => '23000',
        ...just a few codes...
   };


> > > However, I'm not certain
> > > that many drivers actually support $h->state(), or if they do, if they're
> > > conforming to the "standard" (presumably some SQL CLI  std ?).
> > > If everybody adheres to that, then users can do a lookup of the
> > > appropriate SQLSTATE in the <insert SQL manual here> book,
> > > and key off the SQLSTATE value for disposition.

Ideally. It'll never be comprehensive, but that doesn't mean it
can't be useful.

I'd expect to see existing code like:

  $dbh->do("INSERT ...");
  if ($dbh->err =~ /duplicate/i) ...

look like this:

  $dbh->do("INSERT ...");
  if ($dbh->state eq '23505' or !$dbh->state && $dbh->err =~ /duplicate/i) ...

or just check for any of the "Integrity Constraint Violation" class of errors:

  if ($dbh->state =~ /^23/   or !$dbh->state && $dbh->err =~ /duplicate/i) ...

And that's a good example because the first two chars of SQLSTATE are a good
way to check for a 'class' of error.

Naturally there's little point in doing all this for applications that'll only
ever work with one database. The real goal here is to help CPAN modules that
need to be able to work well with many databases.


> > I don't think it will fly.  There are too many DBMS-specific problems 
> > diagnosed by DBMS-specific values of SQLSTATE (or, in some cases, 
> > DBMS-non-specific values - Informix has a tendency to set 
> > SQLSTATE=IX000 - an Informix-specific error occurred; look at SQLCODE 
> > to see what really went wrong) for it to be sensible to do the mapping.
> 
> Sybase (when used with OpenClient, which is what DBD::Sybase does) does
> not set SQLSTATE at all...
> 
> > I, for one, have zero intention of going through 30,000 message codes 
> > and mapping them to anything resembling a standard.
> 
> Indeed...

I wouldn't expect you to. But do you think you could manage 5 or 10?

Tim.

References:
http://www-rohan.sdsu.edu/doc/oracle/server803/A54661_01/err.htm#3146
http://www.postgresql.org/docs/7.4/interactive/errcodes-appendix.html
http://www.mysql.com/doc/en/Error-returns.html
http://www-306.ibm.com/software/data/db2/everyplace/doc/infocenters/enu/dbeapr0902.htm#HDRSQL11
http://developer.mimer.com/documentation/html_92/Mimer_SQL_Engine_DocSet/App_Return_Codes2.html#wp1112282

Reply via email to