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?

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.

Reply via email to