1//  Copyright (c) 2014 Couchbase, Inc.
2//  Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
3//  except in compliance with the License. You may obtain a copy of the License at
4//    http://www.apache.org/licenses/LICENSE-2.0
5//  Unless required by applicable law or agreed to in writing, software distributed under the
6//  License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
7//  either express or implied. See the License for the specific language governing permissions
8//  and limitations under the License.
9
10package planner
11
12import (
13	"github.com/couchbase/query/expression"
14	"github.com/couchbase/query/expression/search"
15	"github.com/couchbase/query/value"
16)
17
18func (this *subset) VisitEq(expr *expression.Eq) (interface{}, error) {
19	switch expr2 := this.expr2.(type) {
20
21	case *expression.LE:
22		if expr.First().EquivalentTo(expr2.First()) {
23			return LessThanOrEquals(expr.Second(), expr2.Second()), nil
24		}
25
26		if expr.Second().EquivalentTo(expr2.First()) {
27			return LessThanOrEquals(expr.First(), expr2.Second()), nil
28		}
29
30		if expr.First().EquivalentTo(expr2.Second()) {
31			return LessThanOrEquals(expr2.First(), expr.Second()), nil
32		}
33
34		if expr.Second().EquivalentTo(expr2.Second()) {
35			return LessThanOrEquals(expr2.First(), expr.First()), nil
36		}
37
38		return false, nil
39
40	case *expression.LT:
41		if expr.First().EquivalentTo(expr2.First()) {
42			return LessThan(expr.Second(), expr2.Second()), nil
43		}
44
45		if expr.Second().EquivalentTo(expr2.First()) {
46			return LessThan(expr.First(), expr2.Second()), nil
47		}
48
49		if expr.First().EquivalentTo(expr2.Second()) {
50			return LessThan(expr2.First(), expr.Second()), nil
51		}
52
53		if expr.Second().EquivalentTo(expr2.Second()) {
54			return LessThan(expr2.First(), expr.First()), nil
55		}
56
57		return false, nil
58
59	case *expression.In:
60		acons, ok := expr2.Second().(*expression.ArrayConstruct)
61		if !ok {
62			return false, nil
63		}
64
65		var rhs expression.Expression
66		if expr.First().EquivalentTo(expr2.First()) {
67			rhs = expr.Second()
68		} else if expr.Second().EquivalentTo(expr2.First()) {
69			rhs = expr.First()
70		} else {
71			return false, nil
72		}
73
74		for _, op := range acons.Operands() {
75			if rhs.EquivalentTo(op) {
76				return true, nil
77			}
78		}
79
80		return false, nil
81
82	case *expression.Within:
83		acons, ok := expr2.Second().(*expression.ArrayConstruct)
84		if !ok {
85			return false, nil
86		}
87
88		var rhs expression.Expression
89		if expr.First().EquivalentTo(expr2.First()) {
90			rhs = expr.Second()
91		} else if expr.Second().EquivalentTo(expr2.First()) {
92			rhs = expr.First()
93		} else {
94			return false, nil
95		}
96
97		for _, op := range acons.Operands() {
98			if rhs.EquivalentTo(op) {
99				return true, nil
100			}
101		}
102
103		return false, nil
104
105	case *search.Search:
106		var val value.Value
107
108		if expr.First().EquivalentTo(expr2) {
109			val = expr.Second().Value()
110		} else if expr.Second().EquivalentTo(expr2) {
111			val = expr.First().Value()
112		}
113
114		if val != nil && val.Type() == value.BOOLEAN && val.Truth() {
115			return true, nil
116		}
117
118		return this.visitDefault(expr)
119
120	default:
121		return this.visitDefault(expr)
122	}
123}
124