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.