[DB-SIG] (Database Abstraction Layer) Wrapping DBAPI Exceptions

Peter L. Buschman plblists at iotk.com
Sat Sep 27 13:14:27 EDT 2003


Very cool. :)

That's where I'm going with this too, only I'll be using the same exception 
names as DBAPI.  One of the issues I have with DBAPI
right now is that the arguments passed to exceptions are inconsistent, 
making it hard to get the error message to the end user.
My exceptions will handle this intelligently and pass the error message 
(and possibly optional extra stuff depending on the driver)
in the same format regardless of the underlying driver.

The low-level effect will be a database abstraction layer that makes it 
appear as if all the DBAPI driver authors had coded to the
same style in all the areas where DBAPI offers multiple options ( 
paramstyle, exception arguments, etc., ) Just like DBO, users get
one set of exceptions to trap for, but they are DBAPI-2.0 compliant exceptions.

The high-level effect will go on to extend this architecture, offering 
common features that were never in DBAPI at all, but doing it
for all of the drivers supported at the low-level.  Supporting differences 
between SQL dialects will be in there.

--PLB

At 04:28 PM 9/26/2003 -0400, Jon Franz_antispam wrote:
>As for PDO, it defines its own exception classes for the different types of
>exceptions (connect error, etc),
>and places information about the underlying db module specific exception
>into the string description
>of the exception.  Thus, users of PDO get one set of exceptions to trap for,
>but still get all the information
>they need to track down the cause.
>
>~Jon Franz
>NeuroKode Labs, LLC
>
>----- Original Message -----
>From: "Kevin Jacobs" <jacobs at penguin.theopalgroup.com>
>To: "Peter L. Buschman" <plblists at iotk.com>
>Cc: <db-sig at python.org>
>Sent: Friday, September 26, 2003 7:31 AM
>Subject: Re: [DB-SIG] (Database Abstraction Layer) Wrapping DBAPI Exceptions
>
>
> > On Fri, 26 Sep 2003, Peter L. Buschman wrote:
> > > The next thing I want to do is wrap the DPABI exceptions of the
>underlying
> > > driver and raise my own equivalents ( which will handle
> > > exception arguments consistently... ) whenever they occur.  Here is the
> > > strategy that comes to mind, but I am wondering how the rest of you
>might
> > > handle a case like this?
> >
> > My DB-API abstraction layer virtualizes exceptions by patching the base
> > classes of the driver exception classes:
> >
> > abstract.py:
> >
> >   class Warning                  (StandardError)       : pass
> >   class Error                    (StandardError)       : pass
> >   class   InterfaceError           (Error)             : pass
> >   class   DatabaseError            (Error)             : pass
> >   class     DataError                (DatabaseError)   : pass
> >   class     OperationalError         (DatabaseError)   : pass
> >   class     IntegrityError           (DatabaseError)   : pass
> >   class     InternalError            (DatabaseError)   : pass
> >   class     ProgrammingError         (DatabaseError)   : pass
> >   class     NotSupportedError        (DatabaseError)   : pass
> >
> >   dbapi_exceptions = [ 'Warning',
> >                        'Error',
> >                        'InterfaceError',
> >                        'DatabaseError',
> >                        'DataError',
> >                        'OperationalError',
> >                        'IntegrityError',
> >                        'InternalError',
> >                        'ProgrammingError',
> >                        'NotSupportedError' ]
> >
> >   def __import_exceptions(module):
> >     for e in dbapi_exceptions:
> >       sub_exception    = getattr(module, e)
> >       abstract_exception = globals()[e]
> >       sub_exception.__bases__ += (abstract_exception,)
> >
> > Whenever I import a native DB-API driver, I call __import_exceptions,
>e.g.:
> >
> >   import psycopg, MySQLdb, Sybase, PoPy, pgdb, MSSQL # ...
> >   from   pyPgSQL import PgSQL
> >
> >   __import_exceptions(psycopg)
> >   __import_exceptions(MySQLdb)
> >   __import_exceptions(Sybase)
> >   __import_exceptions(PoPy)
> >   __import_exceptions(pgdb)
> >   __import_exceptions(MSSQL)
> >   __import_exceptions(PgSQL)
> >
> > Now I can catch any DB-API exception from the above modules without
>knowing
> > which one generated it.
> >
> >   def query(dbcon, sql):
> >     cursor = dbcon.cursor()
> >     cursor.execute(sql)
> >     return cursor.fetchall()
> >
> >   def get_accounts(dbcon):
> >     try:
> >       return query(dbcon, 'SELECT ACCOUNTID FROM ACCOUNTS;')
> >     except abstract.ProgrammingError:
> >       # Do not trap errors due to bad SQL
> >       raise
> >     except abstract.DatabaseError:
> >       # All other database related errors return empty results
> >       return []
> >
> > Clearly, this example is a little contrived, but it gets the point across.
> > The above routines do not need to know which underlying driver they are
> > connected to to be able to catch exceptions.  Of course, there are a
> > thousand _other_ things that are not abstracted in this example.
> >
> > Feel free to reuse the above idea.  Just mention me in the credits
> > somewhere.  ;)
> >
> > -Kevin
> >
> >
> > --
> > --
> > Kevin Jacobs
> > The OPAL Group - Enterprise Systems Architect
> > Voice: (440) 871-6725 x 19         E-mail: jacobs at theopalgroup.com
> > Fax:   (440) 871-6722              WWW:    http://www.theopalgroup.com/
> >
> >
> >
> >




More information about the DB-SIG mailing list