def _add_clause_from_filter(self, flt): """ Returns a clause object computed from the given filter flt format is "[!|-|~][ANY |ALL |ONE |NONE |LEN ]<attr>[operator <value>]" """ clause = { "neg": False, "array_mode": None, "len_mode": False, "attr": None, "operator": None, "value": None, } if not flt: return None # Ignore labels (neo4j compatibility) if flt[0] == "#": return None if flt[0] in "-!~": clause["neg"] = True flt = flt[1:] array_modes = ["ANY", "ALL", "ONE", "NONE"] for array_mode in array_modes: if flt.startswith(array_mode + " "): clause["array_mode"] = array_mode flt = flt[len(array_mode) + 1:] break if clause["array_mode"] is None and flt.startswith("LEN "): clause["len_mode"] = True flt = flt[4:] try: clause["operator"] = self.operators_re.search(flt).group() except AttributeError: clause["operator"] = None clause["attr"] = flt else: clause["attr"], value = [ elt.strip() for elt in flt.split(clause["operator"], 1) ] clause["value"] = utils.str2pyval(value) # Validate field # 'addr' is a shortcut for src.addr OR dst.addr if clause["attr"] != "addr": validate_field(clause["attr"]) return clause
def _add_clause_from_filter(self, flt): """ Returns a clause object computed from the given filter flt format is "[!|-|~][ANY |ALL |ONE |NONE |LEN ]<attr>[operator <value>]" """ clause = { 'neg': False, 'array_mode': None, 'len_mode': False, 'attr': None, 'operator': None, 'value': None } if not flt: return None # Ignore labels (neo4j compatibility) if flt[0] == '#': return None if flt[0] in "-!~": clause['neg'] = True flt = flt[1:] array_modes = ['ANY', 'ALL', 'ONE', 'NONE'] for array_mode in array_modes: if flt.startswith(array_mode + ' '): clause['array_mode'] = array_mode flt = flt[len(array_mode) + 1:] break if clause['array_mode'] is None and flt.startswith("LEN "): clause['len_mode'] = True flt = flt[4:] try: clause['operator'] = self.operators_re.search(flt).group() except AttributeError: clause['operator'] = None clause['attr'] = flt else: clause['attr'], value = [ elt.strip() for elt in flt.split(clause['operator'], 1) ] clause['value'] = utils.str2pyval(value) return clause
def _add_clause_from_filter(self, flt, mode="node"): """Returns a WHERE clause (tuple (query, parameters)) from a single filter (no OR). Devs: `flt` **can** be set from an untrusted source. """ if not flt: return None if flt[0] in "-!~": neg = True flt = flt[1:] else: neg = False array_mode = None len_mode = None if flt.startswith("ANY "): array_mode = "ANY" flt = flt[4:] elif flt.startswith("ALL "): array_mode = "ALL" flt = flt[4:] elif flt.startswith("ONE "): array_mode = "SINGLE" flt = flt[4:] elif flt.startswith("NONE "): array_mode = "NONE" flt = flt[5:] elif flt.startswith("LEN "): len_mode = "LENGTH" flt = flt[4:] try: operator = self.operators_re.search(flt).group() except AttributeError: operator = None attr = flt else: attr, value = [elt.strip() for elt in flt.split(operator, 1)] value = utils.str2pyval(value) if attr[0] in "@#": qtype = attr[0] attr = attr[1:] else: qtype = "@" try: # Sorry for the horrendous code -- jalet elements, attr = attr.rsplit('.', 1) if elements == "meta": if mode == "edge": elements = ["linkmeta"] self.meta_link = True elif mode == "node": elements = ["srcmeta", "dstmeta"] self.meta_src = True self.meta_dst = True elif elements == "src.meta": elements = ["srcmeta"] self.meta_src = True elif elements == "dst.meta": elements = ["dstmeta"] self.meta_dst = True else: elements = [elements] except ValueError: if mode == "node": elements = ["src", "dst"] elif mode == "edge": elements = ["link"] else: raise ValueError() else: assert all(self.identifier.search(elt) for elt in elements) assert self.identifier.search(attr) if operator is None: if qtype == "@": return ( "%s(%s)" % ( "NOT " if neg else "", " OR ".join("EXISTS(`%s`.`%s`)" % (elt, attr) for elt in elements), ), {}, ) if qtype == "#": identifier = self.nextid() return ( "%s(%s)" % ( "NOT " if neg else "", " OR ".join("{%s} IN labels(`%s`)" % (identifier, elt) for elt in elements), ), { identifier: attr }, ) if qtype == "@": identifier = self.nextid() operator = self.operators[operator] clauses = [] for elt in elements: attr_expr = "%s.%s" % tuple( cypher_escape(s) for s in (elt, attr)) if array_mode is not None: lval = "x" elif len_mode is not None: lval = "%s(%s)" % (len_mode, attr_expr) else: lval = attr_expr clause_part = "%s %s {%s}" % (lval, operator, identifier) if array_mode is not None: if array_mode in ["ALL", "ANY", "SINGLE"]: prereq = "LENGTH(%s) <> 0 AND" % attr_expr elif array_mode in ["NONE"]: prereq = "LENGTH(%s) = 0 OR" clause_part = "%s %s(x IN %s WHERE %s)" % ( prereq, array_mode, attr_expr, clause_part, ) clauses.append(clause_part) clause = " OR ".join(clauses) if neg: clause = "%s OR NOT (%s)" % ( " OR ".join("NOT EXISTS(`%s`.`%s`)" % (elt, attr) for elt in elements), clause, ) value = Neo4jDB.to_dbprop(attr, value) return ( "%s" % clause, { identifier: value }, ) raise ValueError()
def _add_clause_from_filter(self, flt, mode="node"): """Returns a WHERE clause (tuple (query, parameters)) from a single filter (no OR). Devs: `flt` **can** be set from an untrusted source. """ if not flt: return None try: operator = self.operators_re.search(flt).group() except AttributeError: operator = None attr = flt else: attr, value = [elt.strip() for elt in flt.split(operator, 1)] value = utils.str2pyval(value) if attr[0] in "-!~": neg = True attr = attr[1:] else: neg = False if attr[0] in "@#": qtype = attr[0] attr = attr[1:] else: qtype = "@" try: # Sorry for the horrendous code -- jalet elements, attr = attr.rsplit('.', 1) if elements == "meta": if mode == "edge": elements = ["linkmeta"] self.meta_link = True elif mode == "node": elements = ["srcmeta", "dstmeta"] self.meta_src = True self.meta_dst = True elif elements == "src.meta": elements = ["srcmeta"] self.meta_src = True elif elements == "dst.meta": elements = ["dstmeta"] self.meta_dst = True else: elements = [elements] except ValueError: if mode == "node": elements = ["src", "dst"] elif mode == "edge": elements = ["link"] else: raise ValueError() else: assert all(self.identifier.search(elt) for elt in elements) assert self.identifier.search(attr) if operator is None: if qtype == "@": return ( "%s(%s)" % ( "NOT " if neg else "", " OR ".join( "EXISTS(`%s`.`%s`)" % (elt, attr) for elt in elements ), ), {}, ) if qtype == "#": identifier = self.nextid() return ( "%s(%s)" % ( "NOT " if neg else "", " OR ".join( "{%s} IN labels(`%s`)" % (identifier, elt) for elt in elements ), ), {identifier: attr}, ) if qtype == "@": identifier = self.nextid() operator = self.operators[operator] clause = " OR ".join( "`%s`.`%s` %s {%s}" "" % (elt, attr, operator, identifier) for elt in elements ) if neg: clause = "%s OR NOT (%s)" % ( " OR ".join("NOT EXISTS(`%s`.`%s`)" % (elt, attr) for elt in elements), clause, ) value = Neo4jDB.to_dbprop(attr, value) return ( "%s" % clause, {identifier: value}, ) raise ValueError()
def _add_clause_from_filter(self, flt, mode="node"): """Returns a WHERE clause (tuple (query, parameters)) from a single filter (no OR). Devs: `flt` **can** be set from an untrusted source. """ if not flt: return None if flt[0] in "-!~": neg = True flt = flt[1:] else: neg = False array_mode = None len_mode = None if flt.startswith("ANY "): array_mode = "ANY" flt = flt[4:] elif flt.startswith("ALL "): array_mode = "ALL" flt = flt[4:] elif flt.startswith("ONE "): array_mode = "SINGLE" flt = flt[4:] elif flt.startswith("NONE "): array_mode = "NONE" flt = flt[5:] elif flt.startswith("LEN "): len_mode = "LENGTH" flt = flt[4:] try: operator = self.operators_re.search(flt).group() except AttributeError: operator = None attr = flt else: attr, value = [elt.strip() for elt in flt.split(operator, 1)] value = utils.str2pyval(value) if attr[0] in "@#": qtype = attr[0] attr = attr[1:] else: qtype = "@" try: # Sorry for the horrendous code -- jalet elements, attr = attr.rsplit('.', 1) if elements == "meta": if mode == "edge": elements = ["linkmeta"] self.meta_link = True elif mode == "node": elements = ["srcmeta", "dstmeta"] self.meta_src = True self.meta_dst = True elif elements == "src.meta": elements = ["srcmeta"] self.meta_src = True elif elements == "dst.meta": elements = ["dstmeta"] self.meta_dst = True else: elements = [elements] except ValueError: if mode == "node": elements = ["src", "dst"] elif mode == "edge": elements = ["link"] else: raise ValueError() else: assert all(self.identifier.search(elt) for elt in elements) assert self.identifier.search(attr) if operator is None: if qtype == "@": return ( "%s(%s)" % ( "NOT " if neg else "", " OR ".join( "EXISTS(`%s`.`%s`)" % (elt, attr) for elt in elements ), ), {}, ) if qtype == "#": identifier = self.nextid() return ( "%s(%s)" % ( "NOT " if neg else "", " OR ".join( "{%s} IN labels(`%s`)" % (identifier, elt) for elt in elements ), ), {identifier: attr}, ) if qtype == "@": identifier = self.nextid() operator = self.operators[operator] clauses = [] for elt in elements: attr_expr = "%s.%s" % tuple(cypher_escape(s) for s in (elt, attr)) if array_mode is not None: lval = "x" elif len_mode is not None: lval = "%s(%s)" % (len_mode, attr_expr) else: lval = attr_expr clause_part = "%s %s {%s}" % (lval, operator, identifier) if array_mode is not None: if array_mode in ["ALL", "ANY", "SINGLE"]: prereq = "LENGTH(%s) <> 0 AND" % attr_expr elif array_mode in ["NONE"]: prereq = "LENGTH(%s) = 0 OR" clause_part = "%s %s(x IN %s WHERE %s)" % ( prereq, array_mode, attr_expr, clause_part, ) clauses.append(clause_part) clause = " OR ".join(clauses) if neg: clause = "%s OR NOT (%s)" % ( " OR ".join("NOT EXISTS(`%s`.`%s`)" % (elt, attr) for elt in elements), clause, ) value = Neo4jDB.to_dbprop(attr, value) return ( "%s" % clause, {identifier: value}, ) raise ValueError()