[DB-SIG] Extensions to DB API 2.0

M.-A. Lemburg mal@lemburg.com
Fri, 23 Nov 2001 12:29:47 +0100


I would like to integrate the proposed standard extensions to=20
DB API 2.0 into the DB API PEP in the next few days. If you have
more comments to make, please speak up now.

--
PEP: Addition to PEP 249
Title: Optional Database API Extensions
Version: $Revision: 1.2$
Author: mal@lemburg.com (Marc-Andr=E9 Lemburg)
Status: Draft
Type: Standards Track
Python-Version: 2.3
Created: 23-Oct-2001
Post-History:=20

Abstract

    This pre-PEP should provide a discussion basis for an "Optional
    Extensions" section in the DB API 2.0 standard PEP 249.

    Feel free to add/change text as required.

Problem

    Even though the DB API 2.0 standard already provides a multitude
    of APIs, there are some common situations where a database package
    writer will want to add features which are specific to the
    database, but which could also be implemented for other databases
    as well.

    This pre-PEP will collect these common extensions for subsequent
    inclusion in the DB API 2.0 standard. Note that all extensions
    will be marked "optional", meaning that database writers are free
    to implement them, but are not required to do so in order to have
    a DB API 2.0 compatible package.

Proposed Common Extensions

    As with all DB API optional features, the database module authors
    are free to not implement these additional attributes and methods
    (using them will then result in an AttributeError), to raise
    a NotSupportedError in case the availability can only be checked
    at run-time.

    It has been proposed to make usage of these extensions optionally
    visible to the programmer by issuing Python warnings through the
    Python warning framework. To make this feature useful, the warning
    messages must be standardized in order to be able to mask them.
These
    standard messages are referred to below as "Warning Message".

    Cursor Attribute .rownumber

       This read-only attribute should provide the current 0-based
       index of the cursor in the result set or -1 if the index cannot
       be determined.

       The index can be seen as index of the cursor in a sequence (the
       result set). The next fetch operation will fetch the row
       indexed by .rownumber in that sequence.

       Warning Message: "DB-API extension cursor.rownumber used"

    Connection Attributes .Error, .ProgrammingError, etc.

       All exception classes defined by the DB API standard should be
       exposed on the Connection objects are attributes (in addition
       to being available at module scope).

       These attributes simplify error handling in multi-connection
       environments.

       Warning Message: "DB-API extension connection.<exception> used"

    Cursor Attributes .connection

       This read-only attribute return a reference to the Connection
       object on which the cursor was created.

       The attribute simplifies writing polymorph code in
       multi-connection environments.

       Warning Message: "DB-API extension cursor.connection used"

    Cursor Method .scroll(value[,mode=3D'relative'])

       Scroll the cursor in the result set to a new position according
       to mode.
      =20
       If mode is 'relative' (default), value is taken as offset to
       the current position in the result set, if set to 'absolute',
       value states an absolute target position.

       An IndexError should be raised in case a scroll operation would
       leave the result set. In this case, the cursor position is left
       undefined (ideal would be to not move the cursor at all).

       Note: This method should use native scrollable cursors, if
       available , or revert to an emulation for forward-only
       scrollable cursors. The method may raise NotSupportedErrors to
       signal that a specific operation is not supported by the
       database (e.g. backward scrolling).

       Warning Message: "DB-API extension cursor.scroll() used"

    Cursor Attribute .messages

       This is a Python list object to which the interface appends
       tuples (exception class, exception value) for all messages
       which the interfaces receives from the underlying database for
       this cursor.

       The list is cleared by all standard cursor methods calls (prior
       to executing the call) except for the .fetchXXX() calls
       automatically to avoid excessive memory usage and can also be
       cleared by executing "del cursor.messages[:]".

       All error and warning messages generated by the database are
       placed into this list, so checking the list allows the user to
       verify correct operation of the method calls.

       The aim of this attribute is to eliminate the need for a
       Warning exception which often causes problems (some warnings
       really only have informational character).

       Warning Message: "DB-API extension cursor.messages used"

    Connection Attribute .messages

       Same as cursor.messages except that the messages in the list
       are connection oriented.

       The list is cleared automatically by all standard connection
       methods calls (prior to executing the call) to avoid excessive
       memory usage and can also be cleared by executing "del
       connection.messages[:]".

       Warning Message: "DB-API extension connection.messages used"

    Cursor Method .next()
=20
       Return the next row from the currently executing SQL statement
       using the same semantics as .fetchone().  A StopIteration
       exception is raised when the result set is exhausted for Python
       versions 2.2 and later. Previous versions don't have the
       StopIteration exception and so the method should raise an
       IndexError instead.
=20
       Warning Message: "DB-API extension cursor.next() used"

    Cursor Method .__iter__()
=20
       Return self to make cursors compatible to the iteration protocol.

       Warning Message: "DB-API extension cursor.__iter__() used"

    Cursor Attribute .lastrowid

       This read-only attribute provides the rowid of the last
       modified row (most databases return a rowid only when a single
       INSERT operation is performed.) If the operation does not set a
       rowid or if the database does not support rowids, this
       attribute should be set to None.

       The semantics of .lastrowid are undefined in case the last
       executed statement modified more than one row, e.g. when
       using INSERT with .executemany().

       Warning Message: "DB-API extension cursor.lastrowid used"

Proposed Error Handling Extension

    In order to simplify error handling when dealing with databases,
    database module authors may choose to implement user defineable
    error handlers. This section describes a standard way of defining
    these error handlers.

    Cursor/Connection Attribute .errorhandler

       Read/write attribute which references an error handler to call
       in case an error condition is met.=20

       The handler must be a Python callable taking the following
       arguments: errorhandler(connection, cursor, errorclass,
       errorvalue) where connection is a reference to the connection
       on which the cursor operates, cursor a reference to the cursor
       (or None in case the error does not apply to a cursor),
       errorclass is an error class which to instantiate using error
       value as construction arguments.

       The standard error handler should add the error information to
       the appropriate .messages attribute (connection.messages or
       cursor.messages) and raise the exception defined by the given
       errorclass and errorvalue parameters.

       If no errorhandler is set (the attribute is None), the standard
       error handling scheme as outlined above, should be applied.

       Warning Message: "DB-API extension .errorhandler used"

    Cursors should inherit the .errorhandler setting from their
    connection objects.

Proposed Informational Extensions

    A very common question on the DB-SIG mailing list is how to
    construct a dictionary out of the tuples returned by .fetchxxx().

    There are several existing tools available which provide helpers
    for this task. Most of them use the approach of using the column
    names defined in the cursor attribute .description as basis for
    the keys in the row dictionary.

    Note that the reason for not extending the DB API specification
    to also support dictionary return values for the .fetchxxx() methods
    is that this approach has several drawbacks:=20

    * Some databases don't support case-sensitive column names or
      auto-convert them to all lowercase or all uppercase characters.
=20
    * Columns in the result set which are generated by the query (e.g.
      using SQL functions) don't map to table column names and databases
      usually generate names for these columns in a very database
      specific way.

    As a result, accessing the columns through dictionary keys varies
    between databases and makes writing portable code impossible.

Scope

    This PEP only affects database modules/packages which adhere to
    the Python DB API 2.0 standard. Some of these extensions may
    become manditory features in future DB API standard versions.

Copyright

    This document has been placed in the public domain.

=0C
Local Variables:
mode: indented-text
indent-tabs-mode: nil
End:
--=20
Marc-Andre Lemburg
CEO eGenix.com Software GmbH
______________________________________________________________________
Consulting & Company:                           http://www.egenix.com/
Python Software:                        http://www.lemburg.com/python/