Fix #52: query matcher doesn't handle arrays tables Also improve coverage of query matcher.
diff --git a/match.go b/match.go index 085d294..48b0f2a 100644 --- a/match.go +++ b/match.go
@@ -67,7 +67,14 @@ } func (f *matchKeyFn) call(node interface{}, ctx *queryContext) { - if tree, ok := node.(*TomlTree); ok { + if array, ok := node.([]*TomlTree); ok { + for _, tree := range array { + item := tree.values[f.Name] + if item != nil { + f.next.call(item, ctx) + } + } + } else if tree, ok := node.(*TomlTree); ok { item := tree.values[f.Name] if item != nil { f.next.call(item, ctx)
diff --git a/parser_test.go b/parser_test.go index d21604a..710a922 100644 --- a/parser_test.go +++ b/parser_test.go
@@ -542,6 +542,28 @@ }) } +func TestParseKeyGroupArrayQueryExample(t *testing.T) { + tree, err := Load(` + [[book]] + title = "The Stand" + author = "Stephen King" + [[book]] + title = "For Whom the Bell Tolls" + author = "Ernest Hemmingway" + [[book]] + title = "Neuromancer" + author = "William Gibson" + `) + + assertTree(t, tree, err, map[string]interface{}{ + "book": []map[string]interface{}{ + {"title": "The Stand", "author": "Stephen King"}, + {"title": "For Whom the Bell Tolls", "author": "Ernest Hemmingway"}, + {"title": "Neuromancer", "author": "William Gibson"}, + }, + }) +} + func TestParseKeyGroupArraySpec(t *testing.T) { tree, err := Load("[[fruit]]\n name=\"apple\"\n [fruit.physical]\n color=\"red\"\n shape=\"round\"\n [[fruit]]\n name=\"banana\"") assertTree(t, tree, err, map[string]interface{}{
diff --git a/query.go b/query.go index 597f4ff..e255bbe 100644 --- a/query.go +++ b/query.go
@@ -29,7 +29,16 @@ // Set of values within a QueryResult. The order of values is not guaranteed // to be in document order, and may be different each time a query is executed. func (r *QueryResult) Values() []interface{} { - return r.items + values := make([]interface{}, len(r.items)) + for i, v := range r.items { + o, ok := v.(*tomlValue) + if ok { + values[i] = o.value + } else { + values[i] = v + } + } + return values } // Set of positions for values within a QueryResult. Each index in Positions()
diff --git a/query_test.go b/query_test.go new file mode 100644 index 0000000..81818ba --- /dev/null +++ b/query_test.go
@@ -0,0 +1,59 @@ +package toml + +import ( + "testing" +) + +func assertArrayContainsInAnyOrder(t *testing.T, array []interface{}, objects ...interface{}) { + if (len(array) != len(objects)) { + t.Fatalf("array contains %d objects but %d are expected", len(array), len(objects)) + } + + for _, o := range objects { + found := false + for _, a := range array { + if a == o { + found = true + break + } + } + if !found { + t.Fatal(o, "not found in array", array) + } + } +} + +func TestQueryExample(t *testing.T) { + config, _ := Load(` + [[book]] + title = "The Stand" + author = "Stephen King" + [[book]] + title = "For Whom the Bell Tolls" + author = "Ernest Hemmingway" + [[book]] + title = "Neuromancer" + author = "William Gibson" + `) + + authors, _ := config.Query("$.book.author") + names := authors.Values() + if len(names) != 3 { + t.Fatalf("query should return 3 names but returned %d", len(names)) + } + assertArrayContainsInAnyOrder(t, names, "Stephen King", "Ernest Hemmingway", "William Gibson") +} + +func TestQueryReadmeExample(t *testing.T) { + config, _ := Load(` +[postgres] +user = "pelletier" +password = "mypassword" +`) + results, _ := config.Query("$..[user,password]") + values := results.Values() + if len(values) != 2 { + t.Fatalf("query should return 2 values but returned %d", len(values)) + } + assertArrayContainsInAnyOrder(t, values, "pelletier", "mypassword") +}