func (this *NNF) VisitNot(expr *expression.Not) (interface{}, error) { err := expr.MapChildren(this) if err != nil { return nil, err } var exp expression.Expression = expr switch operand := expr.Operand().(type) { case *expression.Not: exp = operand.Operand() case *expression.And: operands := make(expression.Expressions, len(operand.Operands())) for i, op := range operand.Operands() { operands[i] = expression.NewNot(op) } exp = expression.NewOr(operands...) case *expression.Or: operands := make(expression.Expressions, len(operand.Operands())) for i, op := range operand.Operands() { operands[i] = expression.NewNot(op) } exp = expression.NewAnd(operands...) case *expression.Eq: exp = expression.NewOr(expression.NewLT(operand.First(), operand.Second()), expression.NewLT(operand.Second(), operand.First())) case *expression.LT: exp = expression.NewLE(operand.Second(), operand.First()) case *expression.LE: exp = expression.NewLT(operand.Second(), operand.First()) } return exp, exp.MapChildren(this) }
func (this *NNF) VisitIn(expr *expression.In) (interface{}, error) { err := expr.MapChildren(this) if err != nil { return nil, err } a, ok := expr.Second().(*expression.ArrayConstruct) if !ok { return expr, nil } first := expr.First() operands := make(expression.Expressions, len(a.Operands())) for i, op := range a.Operands() { operands[i] = expression.NewEq(first, op) } return expression.NewOr(operands...), nil }
func TestConverter(t *testing.T) { s1 := NewJSConverter().Visit( expression.NewLT(constant("a"), constant("b"))) s2 := "(\"a\" < \"b\")" if s1 != s2 { t.Errorf(" mismatch s1 %s s2 %s", s1, s2) } s1 = NewJSConverter().Visit( expression.NewBetween(constant("a"), constant("b"), constant("c"))) s2 = "(\"a\" > \"b\" && \"a\" < \"c\")" if s1 != s2 { t.Errorf(" mismatch s1 %s s2 %s", s1, s2) } s1 = NewJSConverter().Visit(expression.NewAdd( expression.NewSub(constant("a"), constant("b")), expression.NewDiv(constant("a"), constant("b")))) s2 = "((\"a\" - \"b\") + (\"a\" / \"b\"))" if s1 != s2 { t.Errorf(" mismatch s1 %s s2 %s", s1, s2) } s1 = NewJSConverter().Visit(expression.NewLength(constant("abc"))) s2 = "(\"abc\".length)" if s1 != s2 { t.Errorf(" mismatch s1 %s s2 %s", s1, s2) } s1 = NewJSConverter().Visit(expression.NewUpper(constant("abc"))) s2 = "(\"abc\".toUpperCase())" if s1 != s2 { t.Errorf(" mismatch s1 %s s2 %s", s1, s2) } s1 = NewJSConverter().Visit(expression.NewStrToMillis(constant("Wed, 09 Aug 1995 00:00:00"))) s2 = "(Date.parse(\"Wed, 09 Aug 1995 00:00:00\"))" if s1 != s2 { t.Errorf(" mismatch s1 %s s2 %s", s1, s2) } s1 = NewJSConverter().Visit(expression.NewContains(constant("dfgabc"), constant("abc"))) s2 = "(\"dfgabc\".indexOf(\"abc\"))" if s1 != s2 { t.Errorf(" mismatch s1 %s s2 %s", s1, s2) } s1 = NewJSConverter().Visit(expression.NewSubstr(constant("dfgabc"), constant(1), constant(4))) s2 = "(\"dfgabc\".substring(1,4))" if s1 != s2 { t.Errorf(" mismatch s1 %s s2 %s", s1, s2) } s1 = NewJSConverter().Visit(expression.NewAdd(expression.NewContains(constant("dfgabc"), constant("abc")), expression.NewSubstr(constant("dfgabc"), constant(1), constant(4)))) s2 = "((\"dfgabc\".indexOf(\"abc\")) + (\"dfgabc\".substring(1,4)))" if s1 != s2 { t.Errorf(" mismatch s1 %s s2 %s", s1, s2) } doc := expression.NewIdentifier("bucket") m1 := expression.NewField(doc, expression.NewFieldName("id")) m2 := expression.NewField(doc, expression.NewFieldName("type")) s1 = NewJSConverter().Visit(expression.NewOr( expression.NewUpper(m1), expression.NewLower(m2))) s2 = "((`bucket`.`id`.toUpperCase()) || (`bucket`.`type`.toLowerCase()))" if s1 != s2 { t.Errorf(" mismatch s1 %s s2 %s", s1, s2) } doc = expression.NewIdentifier("bucket") m1 = expression.NewField(doc, expression.NewFieldName("geo")) m2 = expression.NewField(m1, expression.NewFieldName("accuracy")) s1 = NewJSConverter().Visit(m2) s2 = "`bucket`.`geo`.`accuracy`" if s1 != s2 { t.Errorf(" mismatch s1 %s s2 %s", s1, s2) } doc = expression.NewIdentifier("bucket") m1 = expression.NewField(doc, expression.NewElement(expression.NewFieldName("address"), constant(0))) s1 = NewJSConverter().Visit(m1) s2 = "`bucket`.`address`[0]" if s1 != s2 { t.Errorf(" mismatch s1 %s s2 %s", s1, s2) } s1 = NewJSConverter().Visit(expression.NewLength(expression.NewElement(doc, expression.NewFieldName("type")))) s2 = "(`bucket`[`type`].length)" if s1 != s2 { t.Errorf(" mismatch s1 %s s2 %s", s1, s2) } }