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
-~----------~----~----~----~------~----~------~--~---

Reply via email to