Skip to content

Commit

Permalink
Add nil comparison to where tpl function
Browse files Browse the repository at this point in the history
`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 gohugoio#1232
  • Loading branch information
tatsushid committed Jun 29, 2015
1 parent 033a13e commit 7d5bb98
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 11 deletions.
26 changes: 15 additions & 11 deletions tpl/template_funcs.go
Expand Up @@ -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
}

var isNil bool
v, isNil = indirect(v)
if isNil {
return false, nil
}
mv, isNil = indirect(mv)
if isNil {
v, vIsNil := indirect(v)
if !v.IsValid() {
vIsNil = true
}
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
}
return false, nil
}

Expand Down
27 changes: 27 additions & 0 deletions tpl/template_funcs_test.go
Expand Up @@ -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}},
{
Expand All @@ -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}},
{
Expand Down Expand Up @@ -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},
Expand Down

0 comments on commit 7d5bb98

Please sign in to comment.