Support nested keys/fields with missing values with the `where` function
authorAnton Harniakou <anton.harniakou@gmail.com>
Sun, 3 Feb 2019 11:03:44 +0000 (14:03 +0300)
committerBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
Wed, 6 Feb 2019 18:53:34 +0000 (19:53 +0100)
Before this commit `where` would produce an error and bail building the
site. Now, `where` simply skips an element of a collection and does not
add it to the final result.

Closes #5637
Closes #5416

tpl/collections/where.go
tpl/collections/where_test.go

index 859353ff09c9cb3718199288b9d01cd6cad9f3a0..2c5dc7f3fac025aad9afc0333d5d995eec6a39ba 100644 (file)
@@ -357,7 +357,7 @@ func (ns *Namespace) checkWhereArray(seqv, kv, mv reflect.Value, path []string,
                                var err error
                                vvv, err = evaluateSubElem(vvv, elemName)
                                if err != nil {
-                                       return nil, err
+                                       continue
                                }
                        }
                } else {
index bf3d5011c0bfd58daae31a0862179ee6bb570d64..fb768cfdeb2e10bea921e64a580343105d51a873 100644 (file)
@@ -159,6 +159,15 @@ func TestWhere(t *testing.T) {
                                {"foo": TstX{A: "c", B: "d"}},
                        },
                },
+               {
+                       seq: []map[string]TstX{
+                               {"baz": TstX{A: "a", B: "b"}}, {"foo": TstX{A: "a", B: "b"}}, {"foo": TstX{A: "c", B: "d"}}, {"foo": TstX{A: "e", B: "f"}},
+                       },
+                       key: "foo.B", match: "d",
+                       expect: []map[string]TstX{
+                               {"foo": TstX{A: "c", B: "d"}},
+                       },
+               },
                {
                        seq: []map[string]TstX{
                                {"foo": TstX{A: "a", B: "b"}}, {"foo": TstX{A: "c", B: "d"}}, {"foo": TstX{A: "e", B: "f"}},
@@ -450,9 +459,17 @@ func TestWhere(t *testing.T) {
                        key: "b", op: ">", match: false,
                        expect: []map[string]bool{},
                },
+               {
+                       seq: []map[string]bool{
+                               {"a": true, "b": false}, {"c": true, "b": true}, {"d": true, "b": false},
+                       },
+                       key: "b.z", match: false,
+                       expect: []map[string]bool{},
+               },
                {seq: (*[]TstX)(nil), key: "A", match: "a", expect: false},
                {seq: TstX{A: "a", B: "b"}, key: "A", match: "a", expect: false},
-               {seq: []map[string]*TstX{{"foo": nil}}, key: "foo.B", match: "d", expect: false},
+               {seq: []map[string]*TstX{{"foo": nil}}, key: "foo.B", match: "d", expect: []map[string]*TstX{}},
+               {seq: []map[string]*TstX{{"foo": nil}}, key: "foo.B.Z", match: "d", expect: []map[string]*TstX{}},
                {
                        seq: []TstX{
                                {A: "a", B: "b"}, {A: "c", B: "d"}, {A: "e", B: "f"},
@@ -484,27 +501,28 @@ func TestWhere(t *testing.T) {
                        },
                },
        } {
-               var results interface{}
-               var err error
+               t.Run(fmt.Sprintf("test case %d for key %s", i, test.key), func(t *testing.T) {
+                       var results interface{}
+                       var err error
 
-               if len(test.op) > 0 {
-                       results, err = ns.Where(test.seq, test.key, test.op, test.match)
-               } else {
-                       results, err = ns.Where(test.seq, test.key, test.match)
-               }
-               if b, ok := test.expect.(bool); ok && !b {
-                       if err == nil {
-                               t.Errorf("[%d] Where didn't return an expected error", i)
+                       if len(test.op) > 0 {
+                               results, err = ns.Where(test.seq, test.key, test.op, test.match)
+                       } else {
+                               results, err = ns.Where(test.seq, test.key, test.match)
                        }
-               } else {
-                       if err != nil {
-                               t.Errorf("[%d] failed: %s", i, err)
-                               continue
-                       }
-                       if !reflect.DeepEqual(results, test.expect) {
-                               t.Errorf("[%d] Where clause matching %v with %v, got %v but expected %v", i, test.key, test.match, results, test.expect)
+                       if b, ok := test.expect.(bool); ok && !b {
+                               if err == nil {
+                                       t.Errorf("[%d] Where didn't return an expected error", i)
+                               }
+                       } else {
+                               if err != nil {
+                                       t.Errorf("[%d] failed: %s", i, err)
+                               }
+                               if !reflect.DeepEqual(results, test.expect) {
+                                       t.Errorf("[%d] Where clause matching %v with %v, got %v but expected %v", i, test.key, test.match, results, test.expect)
+                               }
                        }
-               }
+               })
        }
 
        var err error