Michael Bayer wrote:
> George V. Reilly wrote:
>> I really don't like the
>>     isinstance(other_side,
>> sqlalchemy.sql.expression._BindParamClause))
>> in the middle of _check_side. Is there a cleaner way to do this?
>>
>> I found that a combination of
>> * the above _check_side and two-sided visit_binary
>> * doing a better job of declaring ForeignKey relationships in Columns
>> * some explicit primaryjoins in calls to relation()
>> cleaned up all the cases where SA wasn't providing the ids in queries
>>
>> Perhaps the sharding sample in SA 0.6 could be expanded?

check out r0ddd638f1d90 in mercurial.  I've added the function from the
example below, plus support for in_op(), to the attribute_shard example. 
The old ClauseVisitor method is removed and replaced with this more robust
method.




>
> I think what's needed here is a little more savvy to what the visitors
> package provides.   ClauseVisitor provides support for some of the hefty
> transforming objects SQLA has internally in the sql util package, but for
> "finding things" you're much better off using the functional API, which is
> a lot more flexible.   Anytime you find yourself using "isinstance()",
> which is in fact sometimes necessary, you can instead try to get the
> visitor dispatch system to give you that type instead.   Below I've
> adapted a recipe that is in the beaker example to also include columns and
> operators from binary expressions.   We can certainly add this function to
> the sharding example.  Ideally the sharding API would come with some
> helper functions, if we could identify some that are of very general use.
>
> from sqlalchemy.sql import visitors
>
> def get_comparisons(query):
>
>     binds = {}
>     columns = set()
>     result = []
>     def visit_bindparam(bind):
>         value = query._params.get(bind.key, bind.value)
>
>         # lazyloader may dig a callable in here, intended
>         # to late-evaluate params after autoflush is called.
>         # convert to a scalar value.
>         if callable(value):
>             value = value()
>
>         binds[bind] = value
>
>     def visit_column(column):
>         columns.add(column)
>
>     def visit_binary(binary):
>         if binary.left in columns and binary.right in binds:
>             result.append((binary.left, binary.operator,
> binds[binary.right]))
>
>         elif binary.left in binds and binary.right in columns:
>             result.append((binary.right, binary.operator,
> binds[binary.left]))
>
>     if query._criterion is not None:
>         visitors.traverse_depthfirst(query._criterion, {},
>                     {'bindparam':visit_bindparam,
>                         'binary':visit_binary,
>                         'column':visit_column
>                     }
>         )
>     return result
>
> if __name__ == '__main__':
>     from sqlalchemy import *
>     from sqlalchemy.orm import *
>
>
>     metadata = MetaData()
>
>     users = Table('users', metadata,
>           Column('id', Integer, primary_key=True, ),
>           Column('name', String(30), nullable=False),
>     )
>
>     addresses = Table('addresses', metadata,
>           Column('id', Integer, primary_key=True, ),
>           Column('user_id', None, ForeignKey('users.id')),
>           Column('email_address', String(50), nullable=False)
>           )
>
>     class User(object):
>         pass
>     class Address(object):
>         pass
>
>     mapper(Address, addresses, properties={
>         'user':relationship(User)
>     })
>     mapper(User, users)
>     sess = create_session()
>
>
>     q = sess.query(User).\
>                 filter(User.id==Address.user_id).\
>                 filter(User.name=='foo').\
>                 filter(Address.email_address.like(bindparam('foo'))).\
>                 params(foo='edward')
>
>     for col, op, value in get_comparisons(q):
>         print col.name, op, value
>
>
>
>
>
>> --
>> /George V. Reilly, Seattle
>>
>> --
>> 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.

Reply via email to