Hi Michael,

Thank you for the quick response. I had thought about using a
straightforward OR statement - are you suggesting that this would form
the body of the in_() method on the Comparator or were you referring
more to just compiling the OR statements in the base query?

Also, what is the correct expression for defining a subquery with the
ORM interface (I gather my embedded session.query statement currently
evaluates as a separate statement to return the list of candidates).


ta,


Martin


On May 27, 7:33 pm, Michael Bayer <[EMAIL PROTECTED]> wrote:
> at its most simplistic level, IN is just a bunch of "X=Y" joined
> together via OR.  Can that approach work here ?  (seems like it would
> be the best way considering its polymorphic scalar elements being
> compared).  At a higher level, seems like you'd want to group elements
> of common types together, and produce a list of the form (type1 IN
> (list of type 1s) OR type2 IN (list of type 2s) ....).
>
> On May 27, 2008, at 2:25 PM, Martin Pengelly-Phillips wrote:
>
>
>
> > Hi there,
>
> > Just came back to some code after a bit of a break and can't seem to
> > get my head around how to correctly use the in_ method with a custom
> > comparator and also the orm subquery functionality.
>
> > See attached file for an outline of my approach.
>
> > You will see that I am stuck on how to correctly form the last query:
> > Roughly: select all entities with property (key='association' and
> > value IN (subquery))
>
> > It looks like I need to define an in_() method on my custom
> > comparator and then possibly use the orm subquery() method for the
> > er...subquery.
>
> > It all feels like it should be straight forward, but the gears just
> > aren't turning at the moment so any pointers would be greatly
> > appreciated.
>
> > ta,
>
> > Martin
>
> > import sys
> > from datetime import datetime
> > from sqlalchemy import *
> > from sqlalchemy.orm import *
> > from sqlalchemy.orm.interfaces import *
>
> > # Database
> > engine = create_engine('sqlite:///')
> > metadata = MetaData()
> > Session = scoped_session(sessionmaker(autoflush=True,
> > transactional=False, bind=engine))
> > mapper = Session.mapper
>
> > # Class: Entity
> > #----------------------------------------------
> > class Entity(object):
>
> >    def __init__(self, properties=None):
> >        self.properties = []
> >        if properties is not None:
> >            self.properties.extend(properties)
>
> > # Table: entities
> > #----------------------------------------------
> > entityTable = Table('entities', metadata,
> >                    Column('id', Integer, primary_key=True),
> >                    Column('_entityType', String(30), nullable=False),
> >                 )
>
> > # Table: entitiesPolymorphicProperties
> > #----------------------------------------------
> > entityPolymorphicPropertyTable =
> > Table('entitiesPolymorphicProperties', metadata,
> >                        Column('entity_id', Integer,
> > ForeignKey('entities.id')),
> >                        Column('polymorphicProperty_id', Integer,
> > ForeignKey('polymorphicProperties.id')),
> >                      )
>
> > # Class: PolymorphicProperty
> > #----------------------------------------------
> > class PolymorphicProperty(object):
>
> >    typeMap = {
> >               str:  ('text','text'),
> >               int: ('integer','integer'),
> >               float: ('float','float'),
> >               datetime: ('datetime','datetime'),
> >               Entity: ('entity','entity'),
> >               type(None): (None, None)
> >              }
>
> >    def __init__(self, key=None, value=None):
> >        self.key = key
> >        self.value = value
>
> >    def _getValue(self):
> >        for discriminator, field in self.typeMap.values():
> >            if self.type == discriminator:
> >                return getattr(self, field)
> >        return None
>
> >    def _setValue(self, value):
> >        # Check type of value can be handled
> >        pyType = type(value)
> >        if pyType not in self.typeMap:
> >            if isinstance(value, Entity):
> >                pyType = Entity
> >            else:
> >                raise TypeError(pyType)
>
> >        # Set real values and current type of property
> >        # Resets all real values no longer matching type to None
> >        for fieldType in self.typeMap:
> >            discriminator, field = self.typeMap[fieldType]
> >            fieldValue = None
> >            if pyType == fieldType:
> >                self.type = discriminator
> >                fieldValue = value
> >            if field is not None:
> >                setattr(self, field, fieldValue)
>
> >    def _delValue(self, value):
> >        self._set_value(None)
>
> >    value = property(_getValue, _setValue, _delValue, doc='''Logical
> > value of this property''')
>
> >    # Class: Comparator
> >    #----------------------------------------------
> >    class Comparator(PropComparator):
>
> >        castableMap = {
> >                   int: (Integer, Text, Float),
> >                   str: (Text,),
> >                   float: (Float, Text),
> >                   datetime: (DateTime, Text),
> >                   type(None): (),
> >                  }
>
> >        castTypeMap = {
> >                   int: Integer,
> >                   str: Text,
> >                   float: Float,
> >                   datetime: DateTime,
> >                   }
>
> >        # Function: _case
> >        #     Generate CASE (switch) statement in SQL to pick
> > appropriate field
> >        #----------------------------------------------
> >        def _case(self, castType=Text):
> >            cls = self.prop.parent.class_
> >            whens = []
> >            for fieldType in cls.typeMap:
> >                if fieldType in self.castableMap:
> >                    if castType in self.castableMap[fieldType]:
> >                        prop = cls.typeMap[fieldType]
> >                        if prop[1] is not None:
> >                            whens.append(( text("'%s'" % prop[0]),
> > cast(getattr(cls, prop[1]), castType) ))
> >            return case(whens, cls.type, null())
>
> >        # Function: __eq__
> >        #     Equality comparison operator.
> >        #----------------------------------------------
> >        def __eq__(self, other):
> >            if isinstance(other, Entity):
> >                return self.prop.parent.class_.entity == other
> >            return self._case() == cast(other, Text)
>
> >        # Function: __ne__
> >        #     In-equality comparison operator.
> >        #----------------------------------------------
> >        def __ne__(self, other):
> >            if isinstance(other, Entity):
> >                return self.prop.parent.class_.entity != other
> >            return self._case() != cast(other, Text)
>
> > # Table: polymorphicProperties
> > #----------------------------------------------
> > polymorphicPropertyTable = Table('polymorphicProperties', metadata,
> >                    Column('id', Integer, primary_key=True),
> >                    Column('key', String(20), nullable=False,
> > default='keyword'),
> >                    Column('type', String(15), default=None),
> >                    Column('text', Text, default=None),
> >                    Column('integer', Integer, default=None),
> >                    Column('float', Float, default=None),
> >                    Column('datetime', DateTime, default=None),
>
> >                    Column('entity_id', Integer,
> > ForeignKey('entities.id')),
> >                )
>
> > # Mapping: PolymorphicProperty
> > #----------------------------------------------
> > mapper(PolymorphicProperty,
> >       polymorphicPropertyTable,
> >       properties={
> >               'value':
> > comparable_property(PolymorphicProperty.Comparator,
> > PolymorphicProperty.value),
> >               'entity': relation(Entity),
> >          }
> >       )
>
> > # Mapping: Entity
> > #----------------------------------------------
> > mapper(Entity, entityTable,
> > polymorphic_on=entityTable.c._entityType,
> > polymorphic_identity='Entity',
> >       properties={
> >               'properties': relation(PolymorphicProperty,
> > secondary=entityPolymorphicPropertyTable, backref='entities'),
> >           }
> >       )
>
> > metadata.create_all(engine)
>
> > # Main
> > #----------------------------------------------
> > def main():
>
> >    session = Session()
> >    session.begin()
>
> >    prop1 = PolymorphicProperty(key='username', value='bob')
> >    entity1 = Entity(properties=[prop1])
>
> >    prop2 = PolymorphicProperty(key='resolution', value=5)
> >    prop3 = PolymorphicProperty(key='association', value=entity1)
> >    entity2 = Entity(properties=[prop2, prop3])
>
> >    session.commit()
>
> >    # Entities with property (key=username, value='bob')
> >    print
> > session.query(Entity).filter(Entity.properties.any(key='username',
> > value='bob')).all()
>
> >    # Entities with property (key=resolution, value=5)
> >    print
> > session.query(Entity).filter(Entity.properties.any(key='resolution',
> > value=5)).all()
>
> >    # Entities with property (key=association, value=entity1)
> >    print
> > session
> > .query(Entity).filter(Entity.properties.any(key='association',
> > value=entity1)).all()
>
> >    # Entities with property (key=association, value IN
> > [subquery(Entity).filter(Entity.properties.any(key='username',
> > value='bob'))])
> >    entities =
> > session
> > .query
> > (Entity
> > ).filter(Entity.properties.any(PolymorphicProperty.key=='asset',
>
> > PolymorphicProperty
> > .value
> > .in_
> > (session.query(Entity).filter(Entity.properties.any(key='username',
> > value='bob'))))).all()
>
> >    Session.remove()
> >    return 0
>
> > # Driver
> > #----------------------------------------------
> > if __name__ == '__main__':
> >    sys.exit(main())
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"sqlalchemy" group.
To post to this group, send email to sqlalchemy@googlegroups.com
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to