Re: row_factory and DictCursor
"Joel Nothman" <[email protected]>
| Newsgroups | gmane.comp.python.db.psycopg.devel |
|---|---|
| Message-ID | <[email protected]> |
On Wed, 03 Jun 2009 16:20:12 +1000, James Henstridge <[email protected]> wrote: [snip] > Here is a quick example of the sort of thing I was thinking of using > rownumber: > > class DictConnection(_connection): > def cursor(self, name=None): > cursor = super(DictConnection, self).cursor(name) > field_names = [] > def row_factory(cursor, data): > # Update field descriptions if it is a new result set. > if cursor.rownumber == 0: > field_names[:] = [info[0] for info in cursor.description] > return dict(zip(field_names, data)) > cursor.row_factory = row_factory > return cursor > > Something similar would be possible with for a namedtuple > implementation. In both cases you can get by without a cursor > subclass, which is probably a plus. > > James. Looks very nice (and a very neat way of keeping field_names static to the cursor without requiring a distinct cursor class. Ideally, though, one would like to just be able to pass a cursor factory or row factory definition to an existing object. (We could do this with a row factory factory which is passed a field_names variable!) This implementation is also a bit nuanced in terms of name binding: field_names cannot be bound to something else in row_factory(), and hence a namedtuple implementation would look something like: class DictConnection(_connection): def cursor(self, name=None): cursor = super(DictConnection, self).cursor(name) tuple_cls = [] def row_factory(cursor, data): # Update field descriptions if it is a new result set. if cursor.rownumber == 0: tuple_cls[:] = [namedtuple('NamedTupleRow', (info[0] for info in cursor.description))] return tuple_cls[0](data)) cursor.row_factory = row_factory return cursor Here the list defined in 'tuple_cls = []' is used merely as a mutable placeholder. I would absolutely love to have extras.py rewritten like this, and if we do it right, we don't have to break much. I think passing the row data to the row_factory constructor is the Right Thing To Do, so anyone relying on the old functionality might just have to break. Nonetheless, I'm trying to find uses in open-source: <http://www.google.com/codesearch?q=psycopg2+row_factory>. There is only one result that's not in reference to SQLite and is not the psycopg2 source: skytools (github.com/markokr/skytools-dev.git) inherits from the existing DictRow: the above therefore isn't good enough for compatibility, but the row_factory interface can be changed. - Joel