def to_esfilter(self, schema): output = OrOp("or", [ AndOp("and", [self.when, BooleanOp("boolean", self.then)]), AndOp("and", [NotOp("not", self.when), BooleanOp("boolean", self.els_)]) ]).partial_eval() return output.to_esfilter(schema)
def to_ruby(self, schema): lhs = self.lhs.partial_eval().to_ruby(schema) rhs = self.rhs.partial_eval().to_ruby(schema) if lhs.many: if rhs.many: return AndOp("and", [ Ruby(type=BOOLEAN, expr="(" + lhs.expr + ").size()==(" + rhs.expr + ").size()", frum=self), Ruby(type=BOOLEAN, expr="(" + rhs.expr + ").containsAll(" + lhs.expr + ")", frum=self) ]).to_ruby(schema) else: return Ruby(type=BOOLEAN, expr="(" + lhs.expr + ").contains(" + rhs.expr + ")", frum=self) elif rhs.many: return Ruby(type=BOOLEAN, expr="(" + rhs.expr + ").contains(" + lhs.expr + ")", frum=self) else: return Ruby(type=BOOLEAN, expr="(" + lhs.expr + "==" + rhs.expr + ")", frum=self)
def to_ruby(self, schema): if not self.terms: return NULL.to_ruby(schema) v = self.terms[-1] acc = FirstOp("first", v).partial_eval().to_ruby(schema) for v in reversed(self.terms[:-1]): m = v.missing().partial_eval() e = NotOp("not", m).partial_eval().to_ruby(schema) r = FirstOp("first", v).partial_eval().to_ruby(schema) if r.miss is TRUE: continue elif r.miss is FALSE: acc = r continue elif acc.type == r.type: new_type = r.type elif acc.type == NUMBER and r.type == INTEGER: new_type = NUMBER elif acc.type == INTEGER and r.type == NUMBER: new_type = NUMBER else: new_type = OBJECT acc = Ruby(miss=AndOp("and", [acc.miss, m]).partial_eval(), type=new_type, expr="(" + e.expr + ") ? (" + r.expr + ") : (" + acc.expr + ")", frum=self) return acc
def to_ruby(self, schema): acc = NumberOp("number", self.terms[-1]).partial_eval().to_ruby(schema).expr for t in reversed(self.terms[0:-1]): acc = "Math.min(" + NumberOp("number", t).partial_eval().to_ruby(schema).expr + " , " + acc + ")" return Ruby( miss=AndOp("or", [t.missing() for t in self.terms]), type=NUMBER, expr=acc, frum=self )
def to_es14_script(self, schema, not_null=False, boolean=False, many=True): acc = NumberOp("number", self.terms[-1]).partial_eval().to_es14_script(schema).expr for t in reversed(self.terms[0:-1]): acc = "Math.min(" + NumberOp("number", t).partial_eval().to_es14_script(schema).expr + " , " + acc + ")" return EsScript( miss=AndOp("or", [t.missing() for t in self.terms]), type=NUMBER, expr=acc, frum=self )
def to_esfilter(self, schema): if self.type == BOOLEAN: return OrOp("or", [AndOp("and", [w.when, w.then]) for w in self.whens[:-1]] + self.whens[-1:]).partial_eval().to_esfilter(schema) else: Log.error("do not know how to handle") return ScriptOp( "script", self.to_es_script(schema).script(schema)).to_esfilter(schema)
def __and__(self, other): """ MERGE TWO NestedOp """ if not is_op(other, NestedOp): return AndOp([self, other]) # MERGE elif self.path == other.frum: return NestedOp( self.path, listwrap(self.select) + listwrap(other.select), AndOp([self.where, other.where]), coalesce(self.sort, other.sort), coalesce(self.limit, other.limit), ) # NEST elif startswith_field(other.frum.var, self.path.var): # WE ACHIEVE INTERSECTION BY LIMITING OURSELF TO ONLY THE DEEP OBJECTS # WE ASSUME frum SELECTS WHOLE DOCUMENT, SO self.select IS POSSIBLE return NestedOp( other, self.select, self.where, self.sort, self.limit, ) elif startswith_field(self.path.var, other.frum.var): return NestedOp( self, other.select, other.where, other.sort, other.limit, ) else: return AndOp([self, other])
def partial_eval(self): if is_op(self.lhs, NestedOp): return self.lang[NestedOp( path=self.lhs.frum.partial_eval(), select=IDENTITY, where=AndOp([ self.lhs.where, BasicEqOp(self.lhs.select, self.rhs), ]).partial_eval(), sort=self.lhs.sort.partial_eval(), limit=self.limit.partial_eval(), )] return self.lang[BasicEqOp( [self.lhs.partial_eval(), self.rhs.partial_eval()])]
def es_query_proto(path, selects, wheres, schema): """ RETURN TEMPLATE AND PATH-TO-FILTER AS A 2-TUPLE :param path: THE NESTED PATH (NOT INCLUDING TABLE NAME) :param wheres: MAP FROM path TO LIST OF WHERE CONDITIONS :return: (es_query, filters_map) TUPLE """ output = None last_where = MATCH_ALL for p in reversed(sorted( wheres.keys() | set(selects.keys()))): where = wheres.get(p) select = selects.get(p) if where: where = AndOp("and", where).partial_eval().to_esfilter(schema) if output: where = es_or([es_and([output, where]), where]) else: if output: if last_where is MATCH_ALL: where = es_or([output, MATCH_ALL]) else: where = output else: where = MATCH_ALL if p == ".": output = set_default( { "from": 0, "size": 0, "sort": [], "query": where }, select.to_es() ) else: output = {"nested": { "path": p, "inner_hits": set_default({"size": 100000}, select.to_es()) if select else None, "query": where }} last_where = where return output
def to_ruby(self, schema): value = self.term.to_ruby(schema) if isinstance(self.term, Variable): if value.many: expr = "!" + value.expr + ".isEmpty() && " + value.expr + "[0]==\"T\"" else: expr = value.expr + "==\"T\"" return Ruby(miss=FALSE, type=BOOLEAN, expr=expr, frum=self) if value.type == BOOLEAN: return AndOp( "and", [ExistsOp("exists", self.term), FirstOp("first", self.term)]).partial_eval().to_ruby() else: return ExistsOp("exists", self.term).partial_eval().to_ruby()
def to_ruby(self, schema, not_null=False, boolean=True): if isinstance(self.expr, Variable): if self.expr.var == "_id": return Ruby(type=BOOLEAN, expr="false", frum=self) else: columns = schema.leaves(self.expr.var) if len(columns) == 1: return Ruby(type=BOOLEAN, expr="doc[" + quote(columns[0].es_column) + "].isEmpty()", frum=self) else: return AndOp("and", [ Ruby(type=BOOLEAN, expr="doc[" + quote(c.es_column) + "].isEmpty()", frum=self) for c in columns ]).partial_eval().to_ruby(schema) else: return self.expr.missing().partial_eval().to_ruby(schema)
def to_ruby(self, schema): op, unit = MultiOp.operators[self.op] if self.nulls: calc = op.join( "((" + t.missing().to_ruby(schema).expr + ") ? " + unit + " : (" + NumberOp("number", t).partial_eval().to_ruby(schema).expr + "))" for t in self.terms) return WhenOp( "when", AndOp("and", [t.missing() for t in self.terms]), **{ "then": self.default, "else": Ruby(type=NUMBER, expr=calc, frum=self) }).partial_eval().to_ruby(schema) else: calc = op.join("(" + NumberOp("number", t).to_ruby(schema).expr + ")" for t in self.terms) return WhenOp( "when", OrOp("or", [t.missing() for t in self.terms]), **{ "then": self.default, "else": Ruby(type=NUMBER, expr=calc, frum=self) }).partial_eval().to_ruby(schema)
def to_es14_script(self, schema, not_null=False, boolean=False, many=True): if isinstance(self.expr, Variable): if self.expr.var == "_id": return EsScript(type=BOOLEAN, expr="false", frum=self) else: columns = schema.leaves(self.expr.var) if len(columns) == 1: return EsScript(type=BOOLEAN, expr="doc[" + quote(first(columns).es_column) + "].isEmpty()", frum=self) else: return AndOp("and", [ EsScript( type=BOOLEAN, expr="doc[" + quote(c.es_column) + "].isEmpty()", frum=self ) for c in columns ]).partial_eval().to_es14_script(schema) elif isinstance(self.expr, Literal): return self.expr.missing().to_es14_script(schema) else: return self.expr.missing().partial_eval().to_es14_script(schema)
def to_es14_script(self, schema, not_null=False, boolean=False, many=True): op, unit = _painless_operators[self.op] if self.nulls: calc = op.join( "((" + t.missing().to_es14_script(schema).expr + ") ? " + unit + " : (" + NumberOp("number", t).partial_eval().to_es14_script(schema).expr + "))" for t in self.terms ) return WhenOp( "when", AndOp("and", [t.missing() for t in self.terms]), **{"then": self.default, "else": EsScript(type=NUMBER, expr=calc, frum=self)} ).partial_eval().to_es14_script(schema) else: calc = op.join( "(" + NumberOp("number", t).to_es14_script(schema).expr + ")" for t in self.terms ) return WhenOp( "when", OrOp("or", [t.missing() for t in self.terms]), **{"then": self.default, "else": EsScript(type=NUMBER, expr=calc, frum=self)} ).partial_eval().to_es14_script(schema)
def to_es14_script(self, schema, not_null=False, boolean=False, many=True): lhs = self.lhs.partial_eval().to_es14_script(schema) rhs = self.rhs.partial_eval().to_es14_script(schema) if lhs.many: if rhs.many: return AndOp("and", [ EsScript(type=BOOLEAN, expr="(" + lhs.expr + ").size()==(" + rhs.expr + ").size()", frum=self), EsScript(type=BOOLEAN, expr="(" + rhs.expr + ").containsAll(" + lhs.expr + ")", frum=self) ]).to_es14_script(schema) else: return EsScript(type=BOOLEAN, expr="(" + lhs.expr + ").contains(" + rhs.expr + ")", frum=self) elif rhs.many: return EsScript( type=BOOLEAN, expr="(" + rhs.expr + ").contains(" + lhs.expr + ")", frum=self ) else: return EsScript( type=BOOLEAN, expr="(" + lhs.expr + "==" + rhs.expr + ")", frum=self )