Steffen Hoffmann wrote:
> Reading through the different db connectors I've got the impression,
> that only SQLite is returning an (empty) object in the no-results case.
> I wrote some debug statements into the code as follows:
>
>> r = cursor.execute(sql, src)
>> self.env.log.debug('CURSOR = ' + str(r))
>> self.env.log.debug('ROWSATTR = ' + str(getattr(r, 'rows', None)))
>> if not r is None:
>> row = r.fetchone()
>> self.env.log.debug('ROW = ' + str(row))
>> if not row is None:
>> return row
You should call fetchone() on the cursor, not on the result of
cursor.execute():
cursor.execute(sql, src)
row = cursor.fetchone()
self.env.log.debug('ROW = ' + str(row))
if not row is None:
return row
(And BTW, you can write "row is not None", which is slightly more
readable than "not row is None".)
The reason it works sometimes is that some DB backends return the cursor
itself from cursor.execute(), but this is non-standard.
> This is unexpected, and I can't see any such logic at similar places in
> Trac core (looked i.e. at ticket.model) where fetchone() is used to
> decide on INSERT vs. UPDATE like I'd like to do it too.
If all you want is to find out if a row exists or not, the following may
be slightly more readable:
cursor.execute(sql, src)
for row, in cursor:
# A row exists, do an UPDATE
break
else:
# No row, do an INSERT
Or, turn it the other way, do an UPDATE, then check for the existence of
the row, and if it doesn't exist, do an INSERT:
# Do an UPDATE
cursor.execute(sql, src)
if cursor.fetchone() is None:
# Do an INSERT
This last method has the advantage that the UPSERT (UPDATE or INSERT) is
atomic, as the UPDATE should start a transaction. That's what we do in
the CacheManager, see:
http://trac.edgewall.org/browser//trunk/trac/cache.py?rev=10585&marks=262-266#L249
-- Remy
signature.asc
Description: OpenPGP digital signature
