Add nil comparison to where tpl function

`where` template function's internal condition check function always
returns `false` when a target value doesn't exist or it's nil value but
this behavior makes it difficult to filter values which doesn't have a
particular parameter.

To solve it, this adds nil value comparison to the function.
`where Values ".Param.key" nil` like clause can be used for the case
above.

Only "=", "==", "eq", "!=", "<>", "ne" operators are allowed to be used
with `nil`. If an other operator is passed with `nil`, the condition
check function returns `false` like before.

Fix #1232
This commit is contained in:
Tatsushi Demachi 2015-06-28 02:15:42 +09:00 committed by Bjørn Erik Pedersen
parent 033a13e10e
commit dd732e84f4
2 changed files with 40 additions and 9 deletions

View file

@ -536,17 +536,21 @@ func evaluateSubElem(obj reflect.Value, elemName string) (reflect.Value, error)
}
func checkCondition(v, mv reflect.Value, op string) (bool, error) {
if !v.IsValid() || !mv.IsValid() {
return false, nil
v, vIsNil := indirect(v)
if !v.IsValid() {
vIsNil = true
}
var isNil bool
v, isNil = indirect(v)
if isNil {
return false, nil
mv, mvIsNil := indirect(mv)
if !mv.IsValid() {
mvIsNil = true
}
if vIsNil || mvIsNil {
switch op {
case "", "=", "==", "eq":
return vIsNil == mvIsNil, nil
case "!=", "<>", "ne":
return vIsNil != mvIsNil, nil
}
mv, isNil = indirect(mv)
if isNil {
return false, nil
}

View file

@ -673,6 +673,7 @@ func TestCheckCondition(t *testing.T) {
"",
expect{true, false},
},
{reflect.ValueOf(nil), reflect.ValueOf(nil), "", expect{true, false}},
{reflect.ValueOf(123), reflect.ValueOf(456), "!=", expect{true, false}},
{reflect.ValueOf("foo"), reflect.ValueOf("bar"), "!=", expect{true, false}},
{
@ -681,6 +682,7 @@ func TestCheckCondition(t *testing.T) {
"!=",
expect{true, false},
},
{reflect.ValueOf(123), reflect.ValueOf(nil), "!=", expect{true, false}},
{reflect.ValueOf(456), reflect.ValueOf(123), ">=", expect{true, false}},
{reflect.ValueOf("foo"), reflect.ValueOf("bar"), ">=", expect{true, false}},
{
@ -943,6 +945,31 @@ func TestWhere(t *testing.T) {
{A: "a", B: "b"}, {A: "e", B: "f"},
},
},
{
sequence: []map[string]int{
{"a": 1, "b": 2}, {"a": 3}, {"a": 5, "b": 6},
},
key: "b", op: "", match: nil,
expect: []map[string]int{
{"a": 3},
},
},
{
sequence: []map[string]int{
{"a": 1, "b": 2}, {"a": 3}, {"a": 5, "b": 6},
},
key: "b", op: "!=", match: nil,
expect: []map[string]int{
{"a": 1, "b": 2}, {"a": 5, "b": 6},
},
},
{
sequence: []map[string]int{
{"a": 1, "b": 2}, {"a": 3}, {"a": 5, "b": 6},
},
key: "b", op: ">", match: nil,
expect: []map[string]int{},
},
{sequence: (*[]TstX)(nil), key: "A", match: "a", expect: false},
{sequence: TstX{A: "a", B: "b"}, key: "A", match: "a", expect: false},
{sequence: []map[string]*TstX{{"foo": nil}}, key: "foo.B", match: "d", expect: false},