This snippet builds a query specified as a Python dictionary Copyright (C) 2013 Alan Etkin This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.
class QueryParser(object): """To be used with the web2py execution environment This class is intended as an interface for reading queries submitted via json or other client protocols """ def __init__(self): self.dquery = None def parse(self, dquery): self.dquery = dquery return self.build(self.dquery) def build(self, d): op, first, second = (d["op"], d["first"], d.get("second", None)) built = None if op in ("AND", "OR"): if not (type(first), type(second)) == (dict, dict): raise SyntaxError("Invalid AND/OR query") if op == "AND": built = self.build(first) & self.build(second) else: built = self.build(first) | self.build(second) elif op == "NOT": if first is None: raise SyntaxError("Invalid NOT query") built = ~self.build(first) else: # normal operation (GT, EQ, LT, ...) if isinstance(second, dict) and "tablename" in second: right = db[second["tablename"]][second["fieldname"]] else: right = second left = db[first["tablename"]][first["fieldname"]] if op == "EQ": built = left == right elif op == "NE": built = left != right elif op == "GT": built = left > right elif op == "GE": built = left >= right elif op == "LT": built = left < right elif op == "LE": built = left <= right elif op == "CONTAINS": built = left.contains(right) elif op == "BELONGS": built = left.belongs(right) else: raise SyntaxError("Operator not supported") return built # Simple test. Note that the syntax doesn't follow the output structure # for the Query class myql = [{ "op": "OR", "first": {"op": "AND", "first":{"first": {"tablename": "auth_user", "fieldname": "id"}, "second": 0, "op": "GT"}, "second":{"first": {"tablename": "auth_user", "fieldname": "id"}, "second": 0, "op": "LT"}}, "second": {"op": "NOT", "first":{"first": {"tablename": "auth_user", "fieldname": "id"}, "second": 0, "op": "GE"}, "second":{"first": {"tablename": "auth_user", "fieldname": "id"}, "second": 0, "op": "LE"}} }] myparser = QueryParser() for i, myqd in enumerate(myql): print "################### Query %s ########################" % i print myparser.parse(myqd)
Comments (0)