On Fri, 2013-05-24 at 08:54 -0700, Chris Clark wrote:

> An iterator with values left is always going to be true, if empty it is 
> false:
> 
>  >>> params = xrange(10)
>  >>> if params:
> ...     print True
> ...
> True
>  >>> params = xrange(0)
>  >>> if params:
> ...     print True
> ...
>  >>>
> 
> this is true for generators too.

No, this is not true: it's xrange to be special-cased and has a length:

        In [1]: def emptyiter():
           ...:     return
           ...:     yield 0
           ...: 
        
        In [4]: bool(emptyiter())
        Out[4]: True
        

> > Using the slot, we'd also allow things like these:
> >
> > .execute(sql, 0)
> > .executemany(sql, 0.0)
> 
> I'm OK with these being allowed through, they would NOT be treated as 
> params. If there are param markers in the sql, a (DBMS) error should be 
> raised with "missing bind params" if the driver doe snot then pass in 
> params.
> 
> > .executemany(sql, [0])
> 
> Again, this is valid, a single tuple with an integer value of zero.

For consistency between execute and executemany, I think
".executemany(sql, [0])" should behave as ".execute(sql, 0)", which is
likely to raise an error.


> > Which leads to another idea for DB-API 3: I think we should allow
> > iterators for the parameter list in .executemany(), and perhaps
> > even for the parameter sequence in .execute().
> 
> They should be allowed and I think you are correct we should be explicit 
> in the spec on this.
> 
> I actually have code that relies on passing a generator into executemany 
> (the easiest example is to pass a cursor in for instance or an ETL 
> function that takes a cursor as a param) .

I'm fine with iterators in executemany, not so much in execute. The
reason is that execute (with positional placeholders) requires a well
defined length of the parameters, because if the no. of placeholders is
different from the no. of parameters it should give an error (the error
may be returned by the driver, but as a matter of fact a query with 3
"?" and 2 arguments is an error). If execute received an iterable the
first thing it should do to would be "args = list(args)" to get their
number. Forcing by spec the args to be a sequence the driver can assume
to find len() and __getitem__ working on 0..len-1, and that's about
everything needed to implement parameters passing.

Another question is about its usefulness: the args are regularly object
of different types, you generally don't have an iterable that yields
first an int, then a date, then a string. You generally expect iterators
to yield homogeneous objects.

An iterable as executemany argument, yielding sequences, is quite handy
instead.


-- 
Daniele

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

Reply via email to