[DB-SIG] cx_Oracle 2.5

M.-A. Lemburg mal@lemburg.com
Wed, 17 Jul 2002 16:08:36 +0200


Anthony Tuininga wrote:
> On Wed, 2002-07-17 at 02:06, M.-A. Lemburg wrote:
> 
>>Anthony Tuininga wrote:
>>
>>>What is cx_Oracle?
>>>
>>> 7) Implemented cursor method executemany() which expects a list of
>>>    dictionaries for the arguments
>>
>>As per DB API this should be a sequence of sequences. Dictionaries
>>are not sequences.
> 
> 
> The one problem with passing a list of sequences (lists or tuples) is
> that it would mean that I would have to use bind by position in this
> case when I am using bind by name in all other cases. That would seem to
> me to be inconsistent with the execute() method which expects bind by
> name, don't you think? To me, it would make more sense that execute()
> and executemany() would use the same method of binding; otherwise, if I
> want to use executemany() I have to completely change my SQL statement
> and my bound variables!!? Comments?

Of course, both APIs expose the same interface, that is .execute()
expects a sequence as argument as well. Where did you get the idea
that according to the DB API a dictionary can be passed to
.execute() ?

>>>11) Added cursor method executemanyprepared() which is identical to
>>
>>the
>>
>>>    method executemany() except that it takes a single argument which
>>
>>is
>>
>>>    the number of times to execute a previously prepared statement and
>>>    it assumes that the bind variables already have their values set;
>>>    used for high performance only
>>
>>Such a method is not needed if you implement the .execute()
>>caching of commands as described in the DB API. .prepare()
>>can also nicely hook into this scheme if you expose the prepared
>>command:
>>
>>c.prepare('stuff')
>>c.executemany(c.command, list_of_data_tuples)
> 
> 
> Not true.

That's how mxODBC works, but maybe I'm missing some
magic here. Could it be that you are passing the data
in via C arrays rather than Python objects ?

> I support the following construct:
> 
> defined_vars = c1.execute(some_select_statement)

According to the DB API 2.0 the .execute() return value
should not be used anymore (in DB API 1.0 it was used
to return the number of affected rows).

> # insert code to transform defined_vars (sequence) to bind_vars
> (dictionary)
> c2.setinputsizes(bind_vars)

Again, .setinputsizes() should accept a sequence, not
a dictionary as per the DB API.

> c2.prepare(some_insert_statement)
> c1.fetchraw(num_rows)
> c2.executemanyprepared(num_rows)

How does the data from cursor c1 get to cursor c2 ?

> This code permits a straight copy from the fetch of one statement to the
> input of another. Please keep in mind that this is intended __ONLY__ for
> high performance code as the database API is more than adequate in terms
> of features for handling this stuff -- it just performs at about half to
> one third of the speed!

I see, so it's just an extension for performance reasons.

> BTW, I do support the prepare() method but I always pass None to the
> execute() method to indicate that the previously prepared statement
> ought to be used, rather than passing c.command.

That's tricky... c.command would be more explicit and is
also inline with the specification w/r to the documented
caching mechanism for .execute() et al. Anyway, just a
suggestion.

-- 
Marc-Andre Lemburg
CEO eGenix.com Software GmbH
_______________________________________________________________________
eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,...
Python Consulting:                               http://www.egenix.com/
Python Software:                    http://www.egenix.com/files/python/