Fix #52: query matcher doesn't handle arrays tables
Also improve coverage of query matcher.
This commit is contained in:
@@ -67,7 +67,14 @@ func newMatchKeyFn(name string) *matchKeyFn {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (f *matchKeyFn) call(node interface{}, ctx *queryContext) {
|
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]
|
item := tree.values[f.Name]
|
||||||
if item != nil {
|
if item != nil {
|
||||||
f.next.call(item, ctx)
|
f.next.call(item, ctx)
|
||||||
|
|||||||
@@ -542,6 +542,28 @@ func TestParseKeyGroupArray(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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) {
|
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\"")
|
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{}{
|
assertTree(t, tree, err, map[string]interface{}{
|
||||||
|
|||||||
@@ -29,7 +29,16 @@ func (r *QueryResult) appendResult(node interface{}, pos Position) {
|
|||||||
// Set of values within a QueryResult. The order of values is not guaranteed
|
// 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.
|
// to be in document order, and may be different each time a query is executed.
|
||||||
func (r *QueryResult) Values() []interface{} {
|
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()
|
// Set of positions for values within a QueryResult. Each index in Positions()
|
||||||
|
|||||||
@@ -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")
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user