On Wed, Apr 1, 2009 at 3:16 PM, David Niergarth <[email protected]> wrote:
> > I understand. I was thinking it would make the psycopg2 results more > similar to what you get when using the DAL methods. But if being able > to switch from postgres to some other database mid-project is > important (it's not for us), you'd want to avoid using the DictCursor > extension. We'll just adjust the source when we want to use > DictCursor. Thanks for considering. > > --David This is a general thing, I think --- I would prefer if [1] changing gluon was not necessary, and [2] projects that have made persistence decisions that are non-portable had a way to do that. I'm not sure if the way to do this is w/ a module, but lets think about what might make more sense here than changing gluon... (module?) > > > On Apr 1, 10:36 am, mdipierro <[email protected]> wrote: > > I think that changing the return value of fetchall should be > > considered breaking backward compatibility. Moreover it would make > > postgresql behave differently than the other database backends. > > > > On Apr 1, 7:22 am, David Niergarth <[email protected]> wrote: > > > > > > Is it really backward compatible? Have you tried? > > > > > I tried basic integer indexing and slicing, which work as expected, as > > > does the dictionary interface. I just went through all the scenarios I > > > could think of and found two differences with DictCursor. > > > > > 1) Extended slicing fails with an exception (e.g., row[2:5:2] or > > > row[::-1]). > > > 2) DictCursor objects have the unfortunate list behavior that they > > > can't be used directly for string interpolation, whereas tuples can. > > > > > --David > > > > > Here are the details. Starting with a simple query, > > > > > >>> import psycopg2 > > > >>> query = ('select id, first_name, last_name, email, password, ' > > > ... 'registration_key from auth_user;') > > > > > check the default behavior. > > > > > >>> conn = psycopg2.connect('') > > > >>> cursor = conn.cursor() > > > >>> cursor.execute(query) > > > >>> rs = cursor.fetchall() > > > >>> row = rs[0] > > > >>> row > > > (1, 'Joe', 'Demo', '[email protected]', > > > '4352cd32e514b98bf6d88ccde0775bf3', '') > > > > > Rows are plain tuples by default. > > > > > >>> type(row) > > > <type 'tuple'> > > > >>> default_row = row # preserve the row for later > > > > > Now try with DictConnection. > > > > > >>> import psycopg2.extras > > > >>> conn = psycopg2.extras.DictConnection('') > > > >>> cursor = conn.cursor() > > > >>> cursor.execute(query) > > > >>> rs = cursor.fetchall() > > > >>> row = rs[0] > > > >>> type(row) > > > <class 'psycopg2.extras.DictRow'> > > > > > Results are now DictRows instead of tuples. DictRows repr like lists. > > > >>> row > > > [1, 'Joe', 'Demo', '[email protected]', > > > '4352cd32e514b98bf6d88ccde0775bf3', ''] > > > > > And they have list methods. (Tuples have no non-special methods so > > > this seems ok. > > > > > >>> row.index('Joe') > > > 1 > > > > > They convert nicely to other builtins. > > > > > >>> list(row) > > > [1, 'Joe', 'Demo', '[email protected]', > > > '4352cd32e514b98bf6d88ccde0775bf3', ''] > > > >>> tuple(row) > > > (1, 'Joe', 'Demo', '[email protected]', > > > '4352cd32e514b98bf6d88ccde0775bf3', '') > > > >>> dict(row) > > > {'first_name': 'Joe', 'last_name': 'Demo', 'id': 1, 'password': > > > '4352cd32e514b98bf6d88ccde0775bf3', 'registration_key': '', 'email': > > > '[email protected]'} > > > > > Integer indexing and len() works. > > > > > >>> row[0], row[1], row[2], row[3], row[4], row[5] > > > (1, 'Joe', 'Demo', '[email protected]', > > > '4352cd32e514b98bf6d88ccde0775bf3', '') > > > >>> len(row) > > > 6 > > > > > They also have a dict interface. > > > > > >>> row.keys() > > > ['first_name', 'last_name', 'email', 'password', > > > 'registration_key', 'id'] > > > >>> row['first_name'], row['last_name'], row['id'] > > > ('Joe', 'Demo', 1) > > > > > Slicing works as expected. > > > > > >>> row[:3] > > > [1, 'Joe', 'Demo'] > > > >>> row[-3:] > > > ['[email protected]', '4352cd32e514b98bf6d88ccde0775bf3', ''] > > > >>> row[2:5] > > > ['Demo', '[email protected]', '4352cd32e514b98bf6d88ccde0775bf3'] > > > > > Hmmm, extended slicing fails (Strike 1)... > > > > > >>> row[2:5:-1] > > > Traceback (most recent call last): > > > File "<stdin>", line 1, in <module> > > > File "/usr/lib/python2.5/site-packages/psycopg2/extras.py", line > > > 110, in __getitem__ > > > x = self._index[x] > > > TypeError: unhashable type > > > >>> row[2:5:1] > > > Traceback (most recent call last): > > > File "<stdin>", line 1, in <module> > > > File "/usr/lib/python2.5/site-packages/psycopg2/extras.py", line > > > 110, in __getitem__ > > > x = self._index[x] > > > TypeError: unhashable type > > > > > but it works for regular tuples. > > > > > >>> default_row[2:5:1] > > > ('Demo', '[email protected]', '4352cd32e514b98bf6d88ccde0775bf3') > > > >>> default_row[2:5:-1] > > > () > > > > > Another problem is the difference between tuples and lists when doing > > > string interpolation. String interpolation requires a tuple and fails > > > with a list. For example, > > > > > >>> '%s %s' % ('a', 'b') > > > 'a b' > > > > > >>> '%s %s' % ['a', 'b'] > > > Traceback (most recent call last): > > > File "<stdin>", line 1, in <module> > > > TypeError: not enough arguments for format string > > > > > The DictCursor fails with string interpolation, just like a list > > > (Strike 2), > > > > > >>> '%s %s %s %s %s %s' % row > > > Traceback (most recent call last): > > > File "<stdin>", line 1, in <module> > > > TypeError: not enough arguments for format string > > > > > but works when wrapped with tuple(). > > > > > >>> '%s %s %s %s %s %s' % tuple(row) > > > '1 Joe Demo [email protected] 4352cd32e514b98bf6d88ccde0775bf3 ' > > > > > It was pretty easy to find two ways DictCursor wouldn't be completely > > > backward compatible. It's probably safe to bet there are other edge > > > cases that could be found. > > > --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "web2py Web Framework" group. To post to this group, send email to [email protected] To unsubscribe from this group, send email to [email protected] For more options, visit this group at http://groups.google.com/group/web2py?hl=en -~----------~----~----~----~------~----~------~--~---

