On Oct 14, 2010, at 4:38 AM, Julien Demoor wrote: > Thanks for your reply. > > What you propose would work for me, but in the meantime I need a workaround.
If you need that exact pattern to work, build a TypeDecorator around ARRAY and have it return a tuple around the result. TypeDecorator is described at: http://www.sqlalchemy.org/docs/core/types.html?highlight=typedecorator#sqlalchemy.types.TypeDecorator The SQLAlchemy type is always involved in between where psycopg2 returns data and where unique_list() is called. As far as changing Query, the unique_list() is what makes it such that if you load a Parent object with many Child objects in a joined-load collection, you get just one Parent and not the same Parent for as many Child objects as are in the result set. > I thought of serializing the arrays in SQL, then converting back to tuples > in my code, but the objects contained in the arrays are quite complex to > parse (decimals, datetims...). So I tried patching the ARRAY class to return > tuples when mutable=False, and that had no effect. If I understand > correctly, by the time unique_list() is called, ARRAY hasn't been involved > yet, and the database's array is converted to a Python list by the driver > (psycopg2 in my case). > > The workaround I've found is to make the following change, in > sqlalchemy.orm.query.Query.instances : > > if filtered: > #if single_entity: > # filter = lambda x: util.unique_list(x, util.IdentitySet) > #else: > # filter = util.unique_list > filter = lambda x: util.unique_list(x, util.IdentitySet) > > Should I expect negative side-effects from this? > > -----Message d'origine----- > De : sqlalchemy@googlegroups.com [mailto:sqlalch...@googlegroups.com] De la > part de Michael Bayer > Envoyé : mercredi 13 octobre 2010 23:37 > À : sqlalchemy@googlegroups.com > Objet : Re: [sqlalchemy] Cannot retrieve PostgreSQL array column with > session.query() : TypeError: unhashable type: 'list' > > The Query runs the result through unique_list() anytime there are mapped > entities in the columns list. The ARRAY result, returning a Python list > [], isn't hashable, so thats that. > > If you only queried for columns, it wouldn't be running through > unique_list(). > > I suppose we'd modify ARRAY to return tuples if it's "mutable" flag isn't > set. that could only be in 0.7, though. Let me know if that works for > you, we'll add a ticket (hard for me to say since I never use the ARRAY > type). > > > > On Oct 13, 2010, at 2:22 PM, Julien Demoor wrote: > >> Hello, >> >> The problem I'm seeing is illustrated by the code below. I tried a >> workaround using TypeDecorator with process_result_value returning a >> tuple rather than a list, to no avail. >> >> Any help will be greatly appreciated. >> >> Regards. >> >> Traceback : >> >> Traceback (most recent call last): >> File "satest2.py", line 23, in <module> >> session.query(Foo, 'col').from_statement("SELECT 55 AS foo_bar, >> '{1,2,3}'::integer[] AS col;").first() >> File "/home/user/programs/env/lib/python2.6/site-packages/sqlalchemy/ >> orm/query.py", line 1494, in first >> ret = list(self)[0:1] >> File "/home/user/programs/env/lib/python2.6/site-packages/sqlalchemy/ >> orm/query.py", line 1682, in instances >> rows = filter(rows) >> File "/home/jdemoor/programs/km/lib/python2.6/site-packages/ >> sqlalchemy/util.py", line 1193, in unique_list >> return [x for x in seq if x not in seen and not seen.add(x)] >> TypeError: unhashable type: 'list' >> >> Full code : >> >> import os >> from sqlalchemy import create_engine, Table, Integer, MetaData, Column >> from sqlalchemy.orm import create_session, mapper >> >> sa_engine = create_engine(os.environ['TEST_DSN']) >> session = create_session(sa_engine, autoflush=True, >> expire_on_commit=True, autocommit=False) >> >> metadata = MetaData() >> foo = Table('foo', metadata, Column('bar', Integer, primary_key=True)) >> class Foo(object): >> pass >> mapper(Foo, foo) >> >> # This works >> assert session.query('col').from_statement("SELECT 'abc' AS >> col;").first() == ('abc',) >> assert session.query('col').from_statement("SELECT >> '{1,2,3}'::integer[] AS col;").first() == ([1,2,3],) >> assert session.query('col1', 'col2').from_statement("SELECT >> '{1,2,3}'::integer[] AS col1, 'abc' AS col2;").first() == ([1,2,3], >> 'abc') >> foo_obj = session.query(Foo).from_statement("SELECT 1 AS >> foo_bar;").first() >> assert foo_obj.bar == 1 >> >> try: >> # This fails >> session.query(Foo, 'col').from_statement("SELECT 55 AS foo_bar, >> '{1,2,3}'::integer[] AS col;").first() >> except TypeError, e: >> print e >> >> from sqlalchemy.dialects.postgresql.base import ARRAY >> col = Column('col', ARRAY(Integer, mutable=False)) >> try: >> # This fails too >> session.query(Foo, col).from_statement("SELECT 55 AS foo_bar, >> '{1,2,3}'::integer[] AS col;").first() >> except TypeError, e: >> print e >> >> -- >> You received this message because you are subscribed to the Google Groups > "sqlalchemy" group. >> To post to this group, send email to sqlalch...@googlegroups.com. >> To unsubscribe from this group, send email to > sqlalchemy+unsubscr...@googlegroups.com. >> For more options, visit this group at > http://groups.google.com/group/sqlalchemy?hl=en. >> > > -- > You received this message because you are subscribed to the Google Groups > "sqlalchemy" group. > To post to this group, send email to sqlalch...@googlegroups.com. > To unsubscribe from this group, send email to > sqlalchemy+unsubscr...@googlegroups.com. > For more options, visit this group at > http://groups.google.com/group/sqlalchemy?hl=en. > > > -- > You received this message because you are subscribed to the Google Groups > "sqlalchemy" group. > To post to this group, send email to sqlalch...@googlegroups.com. > To unsubscribe from this group, send email to > sqlalchemy+unsubscr...@googlegroups.com. > For more options, visit this group at > http://groups.google.com/group/sqlalchemy?hl=en. > -- You received this message because you are subscribed to the Google Groups "sqlalchemy" group. To post to this group, send email to sqlalch...@googlegroups.com. To unsubscribe from this group, send email to sqlalchemy+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/sqlalchemy?hl=en.