Thanks for your help! It was key knowing that I was going in the right direction.
The problem was that I'm stup... erm... I mean... erm... that I made a bad mistake (beginner's one)... I was getting the comparator for the Product class: (getattr(Product, "__eq__")) instead of the comparator for the field/synonym (if I wanted to check for "model == 'foo'", I needed to get: getattr(Product.model, "__eq__"). Yey!! It works! Thank you so much!! 2011/1/16 Michael Bayer <mike...@zzzcomputing.com>: > > On Jan 15, 2011, at 10:53 PM, Hector Blanco wrote: > >> Hello list... >> >> I would like to allow the users to perform certain queries without me >> (or well... my server) knowing in advance what those queries are going >> to be (without hard-coding the query). >> >> For instance: I have a “Product” class. One of it's fields is >> "manufacturer" and another is "model" >> >> class Product(declarativeBase): >> def __init__(self): >> self.model = "" >> self.manufacturer = "" >> >> I would like the user be able to input an string with a query, such as >> “Product.model != 'foo' or Product.model != 'bar'” >> or: >> "Product.model == 'foo' && Product.manufacturer == 'bar'" >> >> I have created a little Python module (queryTree) that tokenizes the >> string and generates a tree for that kind of queries. For the last one >> mentioned above, it would be something like: >> >> >> sqlalchemy.and_ >> / \ >> == == >> / \ / \ >> Product.model "foo" Product.manufacturer "bar" >> >> 1) The “&&” string can be converted to (stored as) the sqlalchemy.and_ method >> 2) The fields of Product are sqlalchemy.orm.synonym(s). If I pass my >> tree module the class I'm going to perform the query for, it can call >> getattr(cls, "model") and get the synonym (I mean: get the >> Product.model synonym itself instead of the “model” string) >> 3) Equally, the comparators are get with getattr(Product, "__eq__") or >> getattr(Product, "__ne__") so I can store in the tree node the >> comparator function instead of the string “==” or “!=” >> >> But when I try to run the query: >> from mylibs.product import Product >> queryString = "Product.model == 'foo' && Product.manufacturer == 'bar'" >> session.query(Product.Product).filter(queryTree.getQuery(queryString, >> Product.Product)) >> >> I get an exception: >> File "/home/hbr/Documents/my-cms/backlib/product/ProductManager.py", >> line 62, in getByCustomFilter >> retval = >> Database.session.query(Product.Product).filter(queryTokenizer.getQuery()).all() >> File "<string>", line 1, in <lambda> >> File >> "/home/hbr/.buildout/eggs/SQLAlchemy-0.6.5-py2.6.egg/sqlalchemy/orm/query.py", >> line 52, in generate >> fn(self, *args[1:], **kw) >> File >> "/home/hbr/.buildout/eggs/SQLAlchemy-0.6.5-py2.6.egg/sqlalchemy/orm/query.py", >> line 942, in filter >> "filter() argument must be of type " >> ArgumentError: filter() argument must be of type >> sqlalchemy.sql.ClauseElement or string > > Well everything I can see is correct here, so you just have to ensure > getQuery() is returning the root of your tree (which, if it's an "and_()", or > a "x == y", is in fact an instance of ClauseElement). Don't do anything > with eval() or strings, keep it as a tokenized structure on your end. SQLA's > job is to make it into a string. > > >> >> With some other tests, I've got some other exceptions that made me >> realize that I could possibly modify somehow the nodes of my tree >> until getting "something" that is accepted by MySQL as a valid query, >> but that's kind of cheating... I'd like to use pure SqlAlchemy if >> possible (I trust SqlAlchemy more than my programming skills) :-D > > the system you've built to interpret user input into a SQL expression tree > should have adequate constraints such that only valid expressions are built > in the first place. > > -- > 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 > 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 sqlalchemy@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.