I've been reading the arguments going back and forth over parameter
styles and I have a different suggestion which might help us out of
this morass -- or perhaps provide additional fodder for the flame war
that appears to be starting.... -)

Define the method for cursor.execute() as follows:

def execute(self, statement, *args, **kwargs):
    if args and kwargs:
        raise "Please use a sequence of parameters or a mapping of
parameters, not both"
    if len(args) == 1:
        if isinstance(args[0], dict):
            kwargs = args[0]
        elif isinstance(args[0], (list, tuple)):
            args = args[0]
    if args:
        self._execute_with_sequence(statement, args)
    else:
        self._execute_with_mapping(statement, args)

First, as an aside to this discussion, I would like to suggest adding
the syntactic sugar (*args, *kwargs) in order to avoid having to build
the list, tuple or dictionary when passing arguments to the execute
method. For backwards compatibility you can check the list of
parameters and if the length is one and the first argument is a list,
tuple or dictionary change the arguments to the new style on the fly.
I believe this is more convenient and improves the readability of the
code when large numbers of parameters are passed. You would want to do
something similar for setinputsizes() of course.

Second, and more to the point, this recognizes that there are actually
__two__ parameter styles that can possibly be in effect in a DB API
module -- one that requires a sequence of parameters and another that
requires a mapping -- and these can co-exist without any difficulty.
In other words, the single parameter style that is defined by the
module is inadequate and should be expanded to two at least (one for
sequences and one for mappings).

With this understanding in mind we can then mandate that qmark and
named are the parameter styles that are used -- qmark for the sequence
and named for the mapping. For those who don't care to implement one
or the other they can raise a "NotImplemented" exception. I recognize
that (for example) Oracle does not support qmark natively which means
parsing the SQL and rewriting it to use the numeric parameter style
which is native to Oracle. To avoid the overhead (and possible bugs)
we may wish to add a boolean attribute to connections and cursors
called "nativeparamstyle" which is defaulted to False. The cursor
value would be "inherited" from the connection, of course. For
cx_Oracle, this would mean that when nativeparamstyle is False,
"qmark" and "named" are the parameter styles expected but when
nativeparamstyle is True, "numeric" and "named" are the parameter
styles expected. If I were lazy and didn't want to implement qmark, I
would simply disallow the use of sequences when nativeparamstyle was
False. :-)

I believe this clarifies the preferred parameter styles for database
independent work and allows for database dependent work where desired.
I believe (someone correct me if I'm wrong) that each native database
API uses one parameter style for sequences and one parameter style for
named parameters, with the possibility that one or the other is not
actually supported. Thus there is no need for the "paramstyle" module
attribute. The DB API will indicate what the parameter styles are by
default (qmark, named) and the DB API module documentation can
indicate what the native parameter styles are if the user cares to go
that way.

Comments?

Anthony
_______________________________________________
DB-SIG maillist  -  DB-SIG@python.org
http://mail.python.org/mailman/listinfo/db-sig

Reply via email to