[DB-SIG] PROPOSAL: Portable Argment Format

Jim Fulton jim.fulton@Digicool.com
Tue, 23 Jun 1998 12:40:26 -0400


I'd like to lobby for a portable argument format for the DBI
interface.  While this *does* require parsing SQL, this is
not really all that hard and I think the benefits are well
worth the effort. I volunteer to provide a utility to assist 
with this.

Here's what I think the format needs to do:

  - Not interfere with SQL.  That is, it must be unabiguous
    to find parameters in SQL.  

  - Support optional argument names, which may be given
    a positional interpretation.

  - Capture type information, to make type explicit.

Maybe this is all that's needed.

I propose the following format:

     :(name)code

where : signals a parameter and code is a type code.

Valid type codes are:

    c, b, B, h, H, i, I, l, L, f, d, and s -- 
       as defined in the struct module

    t -- Date/Time
    $ -- Money (???)
    r -- Binary data (raw/blob) gotten from a string
    others...???

Note that, after some consideration, I decided to use ':'
rather than '%' to signal a parameter, because:

  - % has a meaning in string substitution that is
    too similar and not similar enough to sql parameters.
    I don't want to worry about conflicting or confused
    type codes.

  - One might want to use string formating to generate
    sql containing parameter references (without wanting to 
    escape %s).

  - I was too lazy to try to determin if % could be
    confused with some SQL syntax element and figured
    that : was OK because it was used by Oracle. :-)

I'm not wed to ':'. '?' would be OK too.

The name is optional and defaults to a generated name, 
_x, where x is the index of the argument in the
unnamed arguments.  For example:

     select * from spam 
     where foo=:s and bar=:d

is equivalent to:

     select * from spam 
     where foo=:(_0)s and bar=:(_1)d

Note that positional arguments could be given explicitly
and intermixed with non-positional arguments, as in:

     select * from spam 
     where foo=:(_1)s and bar=:(bar)d and baz=:i

is equivalent to:

     select * from spam 
     where foo=:(_1)s and bar=:(bar)d and baz=:(_0)i

Note that arguments may be repeated as in:

     select * from spam
     where x1 > :(minx)i and x2 > :(minx)i and
           w == :s and a == :(_1)i and b < :(_1)i

When used with ODBC, this would be converted to:

     select * from spam
     where x1 > ? and x2 > ? and
           w == ? and a == ? and b < ?

and two of the arguments would have to bound twice.

I propose that non-positional arguments be assigned positions
according to their order of appearence, with positional arguments
ordered before non-positional arguments.  So in the example above, 
the arguments and their positions would be:

    _0   at position 0,
    _1   at position 1, and
    minx at position 2.

I propose that arguments be treated in a similar fashion to 
Python function arguments, allowing either positional or 
non-positional actual arguments.  For example, the signature 
of the above example would be "_0, _1, minx".

Someone could pass the parameters like this:

  sql=("select * from spam "
       "where x1 > :(minx)i and x2 > :(minx)i and "
       "    w == :s and a == :(_1)i and b < :(_1)i")

  c.execute(sql, 'eggs', 10, 20)
  x.execute(sql, 'eggs', 10, minx=20)
  x.execute(sql, _0=eggs, minx=20, _1=10)

I think that this proposal hase a number of advantages over 
the current scheme:

  - It provides greater portability.

  - It provides some measure of type safety.

  - It supports more user-friendly calling mechanism 
    (e.g. keyword arguments)

  - It is more powerful than some database-specific 
    mechanisms.  For example, ODBC's mechanism forces
    parameters that are *used* more than once to be bound 
    more than once.

The only real downside is that module developers may have 
a bit more work to do.  I'll volunteer to reduce the work
required by providing a utility that parses an sql statement
and returns a new SQL statement that uses database-specific
format and that provides information needed to bind parameters.

Jim

--
Jim Fulton           mailto:jim@digicool.com
Technical Director   (888) 344-4332              Python Powered!
Digital Creations    http://www.digicool.com     http://www.python.org

Under US Code Title 47, Sec.227(b)(1)(C), Sec.227(a)(2)(B) This email
address may not be added to any commercial mail list with out my
permission.  Violation of my privacy with advertising or SPAM will
result in a suit for a MINIMUM of $500 damages/incident, $1500 for
repeats.