mirror of
https://github.com/mikefarah/yq.git
synced 2024-12-19 20:19:04 +00:00
Fixed collect op when working with multiple nodes
This commit is contained in:
parent
d41b44dc42
commit
feb97c9872
@ -78,7 +78,7 @@ a:
|
|||||||
```
|
```
|
||||||
then
|
then
|
||||||
```bash
|
```bash
|
||||||
yq eval '.a.[] | select(. == "*og") | [{"path":path, "value":.}]' sample.yml
|
yq eval '.a[] | select(. == "*og") | [{"path":path, "value":.}]' sample.yml
|
||||||
```
|
```
|
||||||
will output
|
will output
|
||||||
```yaml
|
```yaml
|
||||||
|
@ -71,22 +71,26 @@ func (p *expressionPostFixerImpl) ConvertToPostfix(infixTokens []*token) ([]*Ope
|
|||||||
log.Debugf("deleting open bracket from opstack")
|
log.Debugf("deleting open bracket from opstack")
|
||||||
|
|
||||||
//and append a collect to the result
|
//and append a collect to the result
|
||||||
|
|
||||||
// hack - see if there's the optional traverse flag
|
// hack - see if there's the optional traverse flag
|
||||||
// on the close op - move it to the collect op.
|
// on the close op - move it to the traverse array op
|
||||||
// allows for .["cat"]?
|
// allows for .["cat"]?
|
||||||
prefs := traversePreferences{}
|
prefs := traversePreferences{}
|
||||||
closeTokenMatch := string(currentToken.Match.Bytes)
|
closeTokenMatch := string(currentToken.Match.Bytes)
|
||||||
if closeTokenMatch[len(closeTokenMatch)-1:] == "?" {
|
if closeTokenMatch[len(closeTokenMatch)-1:] == "?" {
|
||||||
prefs.OptionalTraverse = true
|
prefs.OptionalTraverse = true
|
||||||
}
|
}
|
||||||
result = append(result, &Operation{OperationType: collectOperator, Preferences: prefs})
|
result = append(result, &Operation{OperationType: collectOperator})
|
||||||
log.Debugf("put collect onto the result")
|
log.Debugf("put collect onto the result")
|
||||||
|
if opener != openCollect {
|
||||||
result = append(result, &Operation{OperationType: shortPipeOpType})
|
result = append(result, &Operation{OperationType: shortPipeOpType})
|
||||||
log.Debugf("put shortpipe onto the result")
|
log.Debugf("put shortpipe onto the result")
|
||||||
|
}
|
||||||
|
|
||||||
//traverseArrayCollect is a sneaky op that needs to be included too
|
//traverseArrayCollect is a sneaky op that needs to be included too
|
||||||
//when closing a []
|
//when closing a ]
|
||||||
if len(opStack) > 0 && opStack[len(opStack)-1].Operation != nil && opStack[len(opStack)-1].Operation.OperationType == traverseArrayOpType {
|
if len(opStack) > 0 && opStack[len(opStack)-1].Operation != nil && opStack[len(opStack)-1].Operation.OperationType == traverseArrayOpType {
|
||||||
|
opStack[len(opStack)-1].Operation.Preferences = prefs
|
||||||
opStack, result = popOpToResult(opStack, result)
|
opStack, result = popOpToResult(opStack, result)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,15 +15,25 @@ var pathTests = []struct {
|
|||||||
expectedTokens []interface{}
|
expectedTokens []interface{}
|
||||||
expectedPostFix []interface{}
|
expectedPostFix []interface{}
|
||||||
}{
|
}{
|
||||||
|
{
|
||||||
|
`[.a, .b]`,
|
||||||
|
append(make([]interface{}, 0), "[", "a", "UNION", "b", "]"),
|
||||||
|
append(make([]interface{}, 0), "a", "b", "UNION", "COLLECT"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
`.[env(myenv)]`,
|
||||||
|
append(make([]interface{}, 0), "SELF", "TRAVERSE_ARRAY", "[", "ENV", "]"),
|
||||||
|
append(make([]interface{}, 0), "SELF", "ENV", "COLLECT", "TRAVERSE_ARRAY"),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
`.["cat"].["dog"]`,
|
`.["cat"].["dog"]`,
|
||||||
append(make([]interface{}, 0), "SELF", "TRAVERSE_ARRAY", "[", "cat (string)", "]", "SHORT_PIPE", "SELF", "TRAVERSE_ARRAY", "[", "dog (string)", "]"),
|
append(make([]interface{}, 0), "SELF", "TRAVERSE_ARRAY", "[", "cat (string)", "]", "SHORT_PIPE", "SELF", "TRAVERSE_ARRAY", "[", "dog (string)", "]"),
|
||||||
append(make([]interface{}, 0), "SELF", "cat (string)", "COLLECT", "SHORT_PIPE", "TRAVERSE_ARRAY", "SELF", "dog (string)", "COLLECT", "SHORT_PIPE", "TRAVERSE_ARRAY", "SHORT_PIPE"),
|
append(make([]interface{}, 0), "SELF", "cat (string)", "COLLECT", "TRAVERSE_ARRAY", "SELF", "dog (string)", "COLLECT", "TRAVERSE_ARRAY", "SHORT_PIPE"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
`.["cat"]`,
|
`.["cat"]`,
|
||||||
append(make([]interface{}, 0), "SELF", "TRAVERSE_ARRAY", "[", "cat (string)", "]"),
|
append(make([]interface{}, 0), "SELF", "TRAVERSE_ARRAY", "[", "cat (string)", "]"),
|
||||||
append(make([]interface{}, 0), "SELF", "cat (string)", "COLLECT", "SHORT_PIPE", "TRAVERSE_ARRAY"),
|
append(make([]interface{}, 0), "SELF", "cat (string)", "COLLECT", "TRAVERSE_ARRAY"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"with(.a;.=3)",
|
"with(.a;.=3)",
|
||||||
@ -53,12 +63,12 @@ var pathTests = []struct {
|
|||||||
{
|
{
|
||||||
`.[0]`,
|
`.[0]`,
|
||||||
append(make([]interface{}, 0), "SELF", "TRAVERSE_ARRAY", "[", "0 (int64)", "]"),
|
append(make([]interface{}, 0), "SELF", "TRAVERSE_ARRAY", "[", "0 (int64)", "]"),
|
||||||
append(make([]interface{}, 0), "SELF", "0 (int64)", "COLLECT", "SHORT_PIPE", "TRAVERSE_ARRAY"),
|
append(make([]interface{}, 0), "SELF", "0 (int64)", "COLLECT", "TRAVERSE_ARRAY"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
`.[0][1]`,
|
`.[0][1]`,
|
||||||
append(make([]interface{}, 0), "SELF", "TRAVERSE_ARRAY", "[", "0 (int64)", "]", "TRAVERSE_ARRAY", "[", "1 (int64)", "]"),
|
append(make([]interface{}, 0), "SELF", "TRAVERSE_ARRAY", "[", "0 (int64)", "]", "TRAVERSE_ARRAY", "[", "1 (int64)", "]"),
|
||||||
append(make([]interface{}, 0), "SELF", "0 (int64)", "COLLECT", "SHORT_PIPE", "TRAVERSE_ARRAY", "1 (int64)", "COLLECT", "SHORT_PIPE", "TRAVERSE_ARRAY"),
|
append(make([]interface{}, 0), "SELF", "0 (int64)", "COLLECT", "TRAVERSE_ARRAY", "1 (int64)", "COLLECT", "TRAVERSE_ARRAY"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
`"\""`,
|
`"\""`,
|
||||||
@ -68,7 +78,7 @@ var pathTests = []struct {
|
|||||||
{
|
{
|
||||||
`[]|join(".")`,
|
`[]|join(".")`,
|
||||||
append(make([]interface{}, 0), "[", "EMPTY", "]", "PIPE", "JOIN", "(", ". (string)", ")"),
|
append(make([]interface{}, 0), "[", "EMPTY", "]", "PIPE", "JOIN", "(", ". (string)", ")"),
|
||||||
append(make([]interface{}, 0), "EMPTY", "COLLECT", "SHORT_PIPE", ". (string)", "JOIN", "PIPE"),
|
append(make([]interface{}, 0), "EMPTY", "COLLECT", ". (string)", "JOIN", "PIPE"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
`{"cool": .b or .c}`,
|
`{"cool": .b or .c}`,
|
||||||
@ -78,7 +88,7 @@ var pathTests = []struct {
|
|||||||
{
|
{
|
||||||
`{"cool": []|join(".")}`,
|
`{"cool": []|join(".")}`,
|
||||||
append(make([]interface{}, 0), "{", "cool (string)", "CREATE_MAP", "[", "EMPTY", "]", "PIPE", "JOIN", "(", ". (string)", ")", "}"),
|
append(make([]interface{}, 0), "{", "cool (string)", "CREATE_MAP", "[", "EMPTY", "]", "PIPE", "JOIN", "(", ". (string)", ")", "}"),
|
||||||
append(make([]interface{}, 0), "cool (string)", "EMPTY", "COLLECT", "SHORT_PIPE", ". (string)", "JOIN", "PIPE", "CREATE_MAP", "COLLECT_OBJECT", "SHORT_PIPE"),
|
append(make([]interface{}, 0), "cool (string)", "EMPTY", "COLLECT", ". (string)", "JOIN", "PIPE", "CREATE_MAP", "COLLECT_OBJECT", "SHORT_PIPE"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
`.a as $item ireduce (0; . + $item)`, // note - add code to shuffle reduce to this position for postfix
|
`.a as $item ireduce (0; . + $item)`, // note - add code to shuffle reduce to this position for postfix
|
||||||
@ -93,7 +103,7 @@ var pathTests = []struct {
|
|||||||
{
|
{
|
||||||
`[]`,
|
`[]`,
|
||||||
append(make([]interface{}, 0), "[", "EMPTY", "]"),
|
append(make([]interface{}, 0), "[", "EMPTY", "]"),
|
||||||
append(make([]interface{}, 0), "EMPTY", "COLLECT", "SHORT_PIPE"),
|
append(make([]interface{}, 0), "EMPTY", "COLLECT"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
`{}`,
|
`{}`,
|
||||||
@ -103,67 +113,67 @@ var pathTests = []struct {
|
|||||||
{
|
{
|
||||||
`[{}]`,
|
`[{}]`,
|
||||||
append(make([]interface{}, 0), "[", "{", "EMPTY", "}", "]"),
|
append(make([]interface{}, 0), "[", "{", "EMPTY", "}", "]"),
|
||||||
append(make([]interface{}, 0), "EMPTY", "COLLECT_OBJECT", "SHORT_PIPE", "COLLECT", "SHORT_PIPE"),
|
append(make([]interface{}, 0), "EMPTY", "COLLECT_OBJECT", "SHORT_PIPE", "COLLECT"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
`.realnames as $names | $names["anon"]`,
|
`.realnames as $names | $names["anon"]`,
|
||||||
append(make([]interface{}, 0), "realnames", "ASSIGN_VARIABLE", "GET_VARIABLE", "PIPE", "GET_VARIABLE", "TRAVERSE_ARRAY", "[", "anon (string)", "]"),
|
append(make([]interface{}, 0), "realnames", "ASSIGN_VARIABLE", "GET_VARIABLE", "PIPE", "GET_VARIABLE", "TRAVERSE_ARRAY", "[", "anon (string)", "]"),
|
||||||
append(make([]interface{}, 0), "realnames", "GET_VARIABLE", "ASSIGN_VARIABLE", "GET_VARIABLE", "anon (string)", "COLLECT", "SHORT_PIPE", "TRAVERSE_ARRAY", "PIPE"),
|
append(make([]interface{}, 0), "realnames", "GET_VARIABLE", "ASSIGN_VARIABLE", "GET_VARIABLE", "anon (string)", "COLLECT", "TRAVERSE_ARRAY", "PIPE"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
`.b[.a]`,
|
`.b[.a]`,
|
||||||
append(make([]interface{}, 0), "b", "TRAVERSE_ARRAY", "[", "a", "]"),
|
append(make([]interface{}, 0), "b", "TRAVERSE_ARRAY", "[", "a", "]"),
|
||||||
append(make([]interface{}, 0), "b", "a", "COLLECT", "SHORT_PIPE", "TRAVERSE_ARRAY"),
|
append(make([]interface{}, 0), "b", "a", "COLLECT", "TRAVERSE_ARRAY"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
`.b[.a]?`,
|
`.b[.a]?`,
|
||||||
append(make([]interface{}, 0), "b", "TRAVERSE_ARRAY", "[", "a", "]"),
|
append(make([]interface{}, 0), "b", "TRAVERSE_ARRAY", "[", "a", "]"),
|
||||||
append(make([]interface{}, 0), "b", "a", "COLLECT", "SHORT_PIPE", "TRAVERSE_ARRAY"),
|
append(make([]interface{}, 0), "b", "a", "COLLECT", "TRAVERSE_ARRAY"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
`.[]`,
|
`.[]`,
|
||||||
append(make([]interface{}, 0), "SELF", "TRAVERSE_ARRAY", "[", "EMPTY", "]"),
|
append(make([]interface{}, 0), "SELF", "TRAVERSE_ARRAY", "[", "EMPTY", "]"),
|
||||||
append(make([]interface{}, 0), "SELF", "EMPTY", "COLLECT", "SHORT_PIPE", "TRAVERSE_ARRAY"),
|
append(make([]interface{}, 0), "SELF", "EMPTY", "COLLECT", "TRAVERSE_ARRAY"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
`.a[]`,
|
`.a[]`,
|
||||||
append(make([]interface{}, 0), "a", "TRAVERSE_ARRAY", "[", "EMPTY", "]"),
|
append(make([]interface{}, 0), "a", "TRAVERSE_ARRAY", "[", "EMPTY", "]"),
|
||||||
append(make([]interface{}, 0), "a", "EMPTY", "COLLECT", "SHORT_PIPE", "TRAVERSE_ARRAY"),
|
append(make([]interface{}, 0), "a", "EMPTY", "COLLECT", "TRAVERSE_ARRAY"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
`.a[]?`,
|
`.a[]?`,
|
||||||
append(make([]interface{}, 0), "a", "TRAVERSE_ARRAY", "[", "EMPTY", "]"),
|
append(make([]interface{}, 0), "a", "TRAVERSE_ARRAY", "[", "EMPTY", "]"),
|
||||||
append(make([]interface{}, 0), "a", "EMPTY", "COLLECT", "SHORT_PIPE", "TRAVERSE_ARRAY"),
|
append(make([]interface{}, 0), "a", "EMPTY", "COLLECT", "TRAVERSE_ARRAY"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
`.a.[]`,
|
`.a.[]`,
|
||||||
append(make([]interface{}, 0), "a", "SHORT_PIPE", "SELF", "TRAVERSE_ARRAY", "[", "EMPTY", "]"),
|
append(make([]interface{}, 0), "a", "SHORT_PIPE", "SELF", "TRAVERSE_ARRAY", "[", "EMPTY", "]"),
|
||||||
append(make([]interface{}, 0), "a", "SELF", "EMPTY", "COLLECT", "SHORT_PIPE", "TRAVERSE_ARRAY", "SHORT_PIPE"),
|
append(make([]interface{}, 0), "a", "SELF", "EMPTY", "COLLECT", "TRAVERSE_ARRAY", "SHORT_PIPE"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
`.a[0]`,
|
`.a[0]`,
|
||||||
append(make([]interface{}, 0), "a", "TRAVERSE_ARRAY", "[", "0 (int64)", "]"),
|
append(make([]interface{}, 0), "a", "TRAVERSE_ARRAY", "[", "0 (int64)", "]"),
|
||||||
append(make([]interface{}, 0), "a", "0 (int64)", "COLLECT", "SHORT_PIPE", "TRAVERSE_ARRAY"),
|
append(make([]interface{}, 0), "a", "0 (int64)", "COLLECT", "TRAVERSE_ARRAY"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
`.a[0]?`,
|
`.a[0]?`,
|
||||||
append(make([]interface{}, 0), "a", "TRAVERSE_ARRAY", "[", "0 (int64)", "]"),
|
append(make([]interface{}, 0), "a", "TRAVERSE_ARRAY", "[", "0 (int64)", "]"),
|
||||||
append(make([]interface{}, 0), "a", "0 (int64)", "COLLECT", "SHORT_PIPE", "TRAVERSE_ARRAY"),
|
append(make([]interface{}, 0), "a", "0 (int64)", "COLLECT", "TRAVERSE_ARRAY"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
`.a.[0]`,
|
`.a.[0]`,
|
||||||
append(make([]interface{}, 0), "a", "SHORT_PIPE", "SELF", "TRAVERSE_ARRAY", "[", "0 (int64)", "]"),
|
append(make([]interface{}, 0), "a", "SHORT_PIPE", "SELF", "TRAVERSE_ARRAY", "[", "0 (int64)", "]"),
|
||||||
append(make([]interface{}, 0), "a", "SELF", "0 (int64)", "COLLECT", "SHORT_PIPE", "TRAVERSE_ARRAY", "SHORT_PIPE"),
|
append(make([]interface{}, 0), "a", "SELF", "0 (int64)", "COLLECT", "TRAVERSE_ARRAY", "SHORT_PIPE"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
`.a[].c`,
|
`.a[].c`,
|
||||||
append(make([]interface{}, 0), "a", "TRAVERSE_ARRAY", "[", "EMPTY", "]", "SHORT_PIPE", "c"),
|
append(make([]interface{}, 0), "a", "TRAVERSE_ARRAY", "[", "EMPTY", "]", "SHORT_PIPE", "c"),
|
||||||
append(make([]interface{}, 0), "a", "EMPTY", "COLLECT", "SHORT_PIPE", "TRAVERSE_ARRAY", "c", "SHORT_PIPE"),
|
append(make([]interface{}, 0), "a", "EMPTY", "COLLECT", "TRAVERSE_ARRAY", "c", "SHORT_PIPE"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
`[3]`,
|
`[3]`,
|
||||||
append(make([]interface{}, 0), "[", "3 (int64)", "]"),
|
append(make([]interface{}, 0), "[", "3 (int64)", "]"),
|
||||||
append(make([]interface{}, 0), "3 (int64)", "COLLECT", "SHORT_PIPE"),
|
append(make([]interface{}, 0), "3 (int64)", "COLLECT"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
`.key.array + .key.array2`,
|
`.key.array + .key.array2`,
|
||||||
@ -183,27 +193,27 @@ var pathTests = []struct {
|
|||||||
{
|
{
|
||||||
`.a | .[].b == "apple"`,
|
`.a | .[].b == "apple"`,
|
||||||
append(make([]interface{}, 0), "a", "PIPE", "SELF", "TRAVERSE_ARRAY", "[", "EMPTY", "]", "SHORT_PIPE", "b", "EQUALS", "apple (string)"),
|
append(make([]interface{}, 0), "a", "PIPE", "SELF", "TRAVERSE_ARRAY", "[", "EMPTY", "]", "SHORT_PIPE", "b", "EQUALS", "apple (string)"),
|
||||||
append(make([]interface{}, 0), "a", "SELF", "EMPTY", "COLLECT", "SHORT_PIPE", "TRAVERSE_ARRAY", "b", "SHORT_PIPE", "apple (string)", "EQUALS", "PIPE"),
|
append(make([]interface{}, 0), "a", "SELF", "EMPTY", "COLLECT", "TRAVERSE_ARRAY", "b", "SHORT_PIPE", "apple (string)", "EQUALS", "PIPE"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
`(.a | .[].b) == "apple"`,
|
`(.a | .[].b) == "apple"`,
|
||||||
append(make([]interface{}, 0), "(", "a", "PIPE", "SELF", "TRAVERSE_ARRAY", "[", "EMPTY", "]", "SHORT_PIPE", "b", ")", "EQUALS", "apple (string)"),
|
append(make([]interface{}, 0), "(", "a", "PIPE", "SELF", "TRAVERSE_ARRAY", "[", "EMPTY", "]", "SHORT_PIPE", "b", ")", "EQUALS", "apple (string)"),
|
||||||
append(make([]interface{}, 0), "a", "SELF", "EMPTY", "COLLECT", "SHORT_PIPE", "TRAVERSE_ARRAY", "b", "SHORT_PIPE", "PIPE", "apple (string)", "EQUALS"),
|
append(make([]interface{}, 0), "a", "SELF", "EMPTY", "COLLECT", "TRAVERSE_ARRAY", "b", "SHORT_PIPE", "PIPE", "apple (string)", "EQUALS"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
`.[] | select(. == "*at")`,
|
`.[] | select(. == "*at")`,
|
||||||
append(make([]interface{}, 0), "SELF", "TRAVERSE_ARRAY", "[", "EMPTY", "]", "PIPE", "SELECT", "(", "SELF", "EQUALS", "*at (string)", ")"),
|
append(make([]interface{}, 0), "SELF", "TRAVERSE_ARRAY", "[", "EMPTY", "]", "PIPE", "SELECT", "(", "SELF", "EQUALS", "*at (string)", ")"),
|
||||||
append(make([]interface{}, 0), "SELF", "EMPTY", "COLLECT", "SHORT_PIPE", "TRAVERSE_ARRAY", "SELF", "*at (string)", "EQUALS", "SELECT", "PIPE"),
|
append(make([]interface{}, 0), "SELF", "EMPTY", "COLLECT", "TRAVERSE_ARRAY", "SELF", "*at (string)", "EQUALS", "SELECT", "PIPE"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
`[true]`,
|
`[true]`,
|
||||||
append(make([]interface{}, 0), "[", "true (bool)", "]"),
|
append(make([]interface{}, 0), "[", "true (bool)", "]"),
|
||||||
append(make([]interface{}, 0), "true (bool)", "COLLECT", "SHORT_PIPE"),
|
append(make([]interface{}, 0), "true (bool)", "COLLECT"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
`[true, false]`,
|
`[true, false]`,
|
||||||
append(make([]interface{}, 0), "[", "true (bool)", "UNION", "false (bool)", "]"),
|
append(make([]interface{}, 0), "[", "true (bool)", "UNION", "false (bool)", "]"),
|
||||||
append(make([]interface{}, 0), "true (bool)", "false (bool)", "UNION", "COLLECT", "SHORT_PIPE"),
|
append(make([]interface{}, 0), "true (bool)", "false (bool)", "UNION", "COLLECT"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
`"mike": .a`,
|
`"mike": .a`,
|
||||||
@ -228,7 +238,7 @@ var pathTests = []struct {
|
|||||||
{
|
{
|
||||||
`{.a: .c, .b.[]: .f.g[]}`,
|
`{.a: .c, .b.[]: .f.g[]}`,
|
||||||
append(make([]interface{}, 0), "{", "a", "CREATE_MAP", "c", "UNION", "b", "SHORT_PIPE", "SELF", "TRAVERSE_ARRAY", "[", "EMPTY", "]", "CREATE_MAP", "f", "SHORT_PIPE", "g", "TRAVERSE_ARRAY", "[", "EMPTY", "]", "}"),
|
append(make([]interface{}, 0), "{", "a", "CREATE_MAP", "c", "UNION", "b", "SHORT_PIPE", "SELF", "TRAVERSE_ARRAY", "[", "EMPTY", "]", "CREATE_MAP", "f", "SHORT_PIPE", "g", "TRAVERSE_ARRAY", "[", "EMPTY", "]", "}"),
|
||||||
append(make([]interface{}, 0), "a", "c", "CREATE_MAP", "b", "SELF", "EMPTY", "COLLECT", "SHORT_PIPE", "TRAVERSE_ARRAY", "SHORT_PIPE", "f", "g", "EMPTY", "COLLECT", "SHORT_PIPE", "TRAVERSE_ARRAY", "SHORT_PIPE", "CREATE_MAP", "UNION", "COLLECT_OBJECT", "SHORT_PIPE"),
|
append(make([]interface{}, 0), "a", "c", "CREATE_MAP", "b", "SELF", "EMPTY", "COLLECT", "TRAVERSE_ARRAY", "SHORT_PIPE", "f", "g", "EMPTY", "COLLECT", "TRAVERSE_ARRAY", "SHORT_PIPE", "CREATE_MAP", "UNION", "COLLECT_OBJECT", "SHORT_PIPE"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
`explode(.a.b)`,
|
`explode(.a.b)`,
|
||||||
|
@ -63,7 +63,7 @@ var createMapOpType = &operationType{Type: "CREATE_MAP", NumArgs: 2, Precedence:
|
|||||||
var shortPipeOpType = &operationType{Type: "SHORT_PIPE", NumArgs: 2, Precedence: 45, Handler: pipeOperator}
|
var shortPipeOpType = &operationType{Type: "SHORT_PIPE", NumArgs: 2, Precedence: 45, Handler: pipeOperator}
|
||||||
|
|
||||||
var lengthOpType = &operationType{Type: "LENGTH", NumArgs: 0, Precedence: 50, Handler: lengthOperator}
|
var lengthOpType = &operationType{Type: "LENGTH", NumArgs: 0, Precedence: 50, Handler: lengthOperator}
|
||||||
var collectOpType = &operationType{Type: "COLLECT", NumArgs: 0, Precedence: 50, Handler: collectOperator}
|
var collectOpType = &operationType{Type: "COLLECT", NumArgs: 1, Precedence: 50, Handler: collectOperator}
|
||||||
var encodeOpType = &operationType{Type: "ENCODE", NumArgs: 0, Precedence: 50, Handler: encodeOperator}
|
var encodeOpType = &operationType{Type: "ENCODE", NumArgs: 0, Precedence: 50, Handler: encodeOperator}
|
||||||
var decodeOpType = &operationType{Type: "DECODE", NumArgs: 0, Precedence: 50, Handler: decodeOperator}
|
var decodeOpType = &operationType{Type: "DECODE", NumArgs: 0, Precedence: 50, Handler: decodeOperator}
|
||||||
|
|
||||||
|
@ -6,6 +6,23 @@ import (
|
|||||||
yaml "gopkg.in/yaml.v3"
|
yaml "gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func collectTogether(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (*CandidateNode, error) {
|
||||||
|
collectedNode := &yaml.Node{Kind: yaml.SequenceNode, Tag: "!!seq"}
|
||||||
|
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
|
||||||
|
candidate := el.Value.(*CandidateNode)
|
||||||
|
collectExpResults, err := d.GetMatchingNodes(context.SingleReadonlyChildContext(candidate), expressionNode)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
for result := collectExpResults.MatchingNodes.Front(); result != nil; result = result.Next() {
|
||||||
|
resultC := result.Value.(*CandidateNode)
|
||||||
|
log.Debugf("found this: %v", NodeToString(resultC))
|
||||||
|
collectedNode.Content = append(collectedNode.Content, unwrapDoc(resultC.Node))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return &CandidateNode{Node: collectedNode}, nil
|
||||||
|
}
|
||||||
|
|
||||||
func collectOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
|
func collectOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
|
||||||
log.Debugf("-- collectOperation")
|
log.Debugf("-- collectOperation")
|
||||||
|
|
||||||
@ -15,26 +32,43 @@ func collectOperator(d *dataTreeNavigator, context Context, expressionNode *Expr
|
|||||||
return context.SingleChildContext(candidate), nil
|
return context.SingleChildContext(candidate), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var evaluateAllTogether = true
|
||||||
|
for matchEl := context.MatchingNodes.Front(); matchEl != nil; matchEl = matchEl.Next() {
|
||||||
|
evaluateAllTogether = evaluateAllTogether && matchEl.Value.(*CandidateNode).EvaluateTogether
|
||||||
|
if !evaluateAllTogether {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if evaluateAllTogether {
|
||||||
|
collectedNode, err := collectTogether(d, context, expressionNode.Rhs)
|
||||||
|
if err != nil {
|
||||||
|
return Context{}, err
|
||||||
|
}
|
||||||
|
return context.SingleChildContext(collectedNode), nil
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
var results = list.New()
|
var results = list.New()
|
||||||
|
|
||||||
node := &yaml.Node{Kind: yaml.SequenceNode, Tag: "!!seq"}
|
|
||||||
var collectC *CandidateNode
|
|
||||||
if context.MatchingNodes.Front() != nil {
|
|
||||||
collectC = context.MatchingNodes.Front().Value.(*CandidateNode).CreateReplacement(node)
|
|
||||||
if len(collectC.Path) > 0 {
|
|
||||||
collectC.Path = collectC.Path[:len(collectC.Path)-1]
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
collectC = &CandidateNode{Node: node}
|
|
||||||
}
|
|
||||||
|
|
||||||
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
|
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
|
||||||
candidate := el.Value.(*CandidateNode)
|
candidate := el.Value.(*CandidateNode)
|
||||||
log.Debugf("Collecting %v", NodeToString(candidate))
|
|
||||||
node.Content = append(node.Content, unwrapDoc(candidate.Node))
|
collectedNode := &yaml.Node{Kind: yaml.SequenceNode, Tag: "!!seq"}
|
||||||
|
collectCandidate := candidate.CreateReplacement(collectedNode)
|
||||||
|
|
||||||
|
collectExpResults, err := d.GetMatchingNodes(context.SingleReadonlyChildContext(candidate), expressionNode.Rhs)
|
||||||
|
if err != nil {
|
||||||
|
return Context{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
results.PushBack(collectC)
|
for result := collectExpResults.MatchingNodes.Front(); result != nil; result = result.Next() {
|
||||||
|
resultC := result.Value.(*CandidateNode)
|
||||||
|
log.Debugf("found this: %v", NodeToString(resultC))
|
||||||
|
collectedNode.Content = append(collectedNode.Content, unwrapDoc(resultC.Node))
|
||||||
|
}
|
||||||
|
|
||||||
|
results.PushBack(collectCandidate)
|
||||||
|
}
|
||||||
|
|
||||||
return context.ChildContext(results), nil
|
return context.ChildContext(results), nil
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,15 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var collectObjectOperatorScenarios = []expressionScenario{
|
var collectObjectOperatorScenarios = []expressionScenario{
|
||||||
|
{
|
||||||
|
skipDoc: true,
|
||||||
|
document: `[{name: cat}, {name: dog}]`,
|
||||||
|
expression: `.[] | {.name: "great"}`,
|
||||||
|
expected: []string{
|
||||||
|
"D0, P[], (!!map)::cat: great\n",
|
||||||
|
"D0, P[], (!!map)::dog: great\n",
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
skipDoc: true,
|
skipDoc: true,
|
||||||
document: "a: []",
|
document: "a: []",
|
||||||
@ -99,9 +108,7 @@ var collectObjectOperatorScenarios = []expressionScenario{
|
|||||||
document: `{name: Mike, pets: {cows: [apl, bba]}}`,
|
document: `{name: Mike, pets: {cows: [apl, bba]}}`,
|
||||||
expression: `{"a":.name, "b":.pets}`,
|
expression: `{"a":.name, "b":.pets}`,
|
||||||
expected: []string{
|
expected: []string{
|
||||||
`D0, P[], (!!map)::a: Mike
|
"D0, P[], (!!map)::a: Mike\nb: {cows: [apl, bba]}\n",
|
||||||
b: {cows: [apl, bba]}
|
|
||||||
`,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -13,6 +13,13 @@ var collectOperatorScenarios = []expressionScenario{
|
|||||||
"D0, P[], ()::a:\n - 0\n",
|
"D0, P[], ()::a:\n - 0\n",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
skipDoc: true,
|
||||||
|
expression: `[1,2,3]`,
|
||||||
|
expected: []string{
|
||||||
|
"D0, P[], (!!seq)::- 1\n- 2\n- 3\n",
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
description: "Collect empty",
|
description: "Collect empty",
|
||||||
document: ``,
|
document: ``,
|
||||||
@ -45,7 +52,8 @@ var collectOperatorScenarios = []expressionScenario{
|
|||||||
expected: []string{
|
expected: []string{
|
||||||
"D0, P[], (!!seq)::- cat\n",
|
"D0, P[], (!!seq)::- cat\n",
|
||||||
},
|
},
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
document: ``,
|
document: ``,
|
||||||
skipDoc: true,
|
skipDoc: true,
|
||||||
expression: `[true]`,
|
expression: `[true]`,
|
||||||
@ -64,7 +72,7 @@ var collectOperatorScenarios = []expressionScenario{
|
|||||||
{
|
{
|
||||||
document: ``,
|
document: ``,
|
||||||
skipDoc: true,
|
skipDoc: true,
|
||||||
expression: `1 | collect`,
|
expression: `collect(1)`,
|
||||||
expected: []string{
|
expected: []string{
|
||||||
"D0, P[], (!!seq)::- 1\n",
|
"D0, P[], (!!seq)::- 1\n",
|
||||||
},
|
},
|
||||||
@ -82,7 +90,16 @@ var collectOperatorScenarios = []expressionScenario{
|
|||||||
expression: `[.a.b.[]]`,
|
expression: `[.a.b.[]]`,
|
||||||
skipDoc: true,
|
skipDoc: true,
|
||||||
expected: []string{
|
expected: []string{
|
||||||
"D0, P[a b], (!!seq)::- 1\n- 2\n- 3\n",
|
"D0, P[], (!!seq)::- 1\n- 2\n- 3\n",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
skipDoc: true,
|
||||||
|
document: `[{name: cat, thing: bor}, {name: dog}]`,
|
||||||
|
expression: `.[] | [.name]`,
|
||||||
|
expected: []string{
|
||||||
|
"D0, P[0], (!!seq)::- cat\n",
|
||||||
|
"D0, P[1], (!!seq)::- dog\n",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -138,9 +138,12 @@ func withEntriesOperator(d *dataTreeNavigator, context Context, expressionNode *
|
|||||||
return Context{}, err
|
return Context{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var results = list.New()
|
||||||
|
|
||||||
|
for el := toEntries.MatchingNodes.Front(); el != nil; el = el.Next() {
|
||||||
//run expression against entries
|
//run expression against entries
|
||||||
// splat toEntries and pipe it into Rhs
|
// splat toEntries and pipe it into Rhs
|
||||||
splatted, err := splat(d, toEntries, traversePreferences{})
|
splatted, err := splat(d, context.SingleChildContext(el.Value.(*CandidateNode)), traversePreferences{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return Context{}, err
|
return Context{}, err
|
||||||
}
|
}
|
||||||
@ -152,11 +155,20 @@ func withEntriesOperator(d *dataTreeNavigator, context Context, expressionNode *
|
|||||||
return Context{}, err
|
return Context{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
collected, err := collectOperator(d, result, expressionNode)
|
selfExpression := &ExpressionNode{Operation: &Operation{OperationType: selfReferenceOpType}}
|
||||||
|
collected, err := collectTogether(d, result, selfExpression)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return Context{}, err
|
return Context{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
//from_entries on the result
|
fromEntries, err := fromEntriesOperator(d, context.SingleChildContext(collected), expressionNode)
|
||||||
return fromEntriesOperator(d, collected, expressionNode)
|
if err != nil {
|
||||||
|
return Context{}, err
|
||||||
|
}
|
||||||
|
results.PushBackList(fromEntries.MatchingNodes)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//from_entries on the result
|
||||||
|
return context.ChildContext(results), nil
|
||||||
}
|
}
|
||||||
|
@ -52,6 +52,16 @@ var entriesOperatorScenarios = []expressionScenario{
|
|||||||
"D0, P[], (!!map)::KEY_a: 1\nKEY_b: 2\n",
|
"D0, P[], (!!map)::KEY_a: 1\nKEY_b: 2\n",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
skipDoc: true,
|
||||||
|
document: `{a: 1, b: 2}`,
|
||||||
|
document2: `{c: 1, d: 2}`,
|
||||||
|
expression: `with_entries(.key |= "KEY_" + .)`,
|
||||||
|
expected: []string{
|
||||||
|
"D0, P[], (!!map)::KEY_a: 1\nKEY_b: 2\n",
|
||||||
|
"D0, P[], (!!map)::KEY_c: 1\nKEY_d: 2\n",
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
description: "Use with_entries to filter the map",
|
description: "Use with_entries to filter the map",
|
||||||
document: `{a: { b: bird }, c: { d: dog }}`,
|
document: `{a: { b: bird }, c: { d: dog }}`,
|
||||||
|
@ -57,16 +57,11 @@ var pathOperatorScenarios = []expressionScenario{
|
|||||||
{
|
{
|
||||||
description: "Print path and value",
|
description: "Print path and value",
|
||||||
document: `{a: [cat, dog, frog]}`,
|
document: `{a: [cat, dog, frog]}`,
|
||||||
expression: `.a.[] | select(. == "*og") | [{"path":path, "value":.}]`,
|
expression: `.a[] | select(. == "*og") | [{"path":path, "value":.}]`,
|
||||||
expected: []string{`D0, P[], (!!seq)::- path:
|
expected: []string{
|
||||||
- a
|
"D0, P[a 1], (!!seq)::- path:\n - a\n - 1\n value: dog\n",
|
||||||
- 1
|
"D0, P[a 2], (!!seq)::- path:\n - a\n - 2\n value: frog\n",
|
||||||
value: dog
|
},
|
||||||
- path:
|
|
||||||
- a
|
|
||||||
- 2
|
|
||||||
value: frog
|
|
||||||
`},
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -187,7 +187,7 @@ var recursiveDescentOperatorScenarios = []expressionScenario{
|
|||||||
document: mergeDocSample,
|
document: mergeDocSample,
|
||||||
expression: `.foobar | [..]`,
|
expression: `.foobar | [..]`,
|
||||||
expected: []string{
|
expected: []string{
|
||||||
"D0, P[], (!!seq)::- c: foobar_c\n !!merge <<: *foo\n thing: foobar_thing\n- foobar_c\n- *foo\n- foobar_thing\n",
|
"D0, P[foobar], (!!seq)::- c: foobar_c\n !!merge <<: *foo\n thing: foobar_thing\n- foobar_c\n- *foo\n- foobar_thing\n",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -195,7 +195,7 @@ var recursiveDescentOperatorScenarios = []expressionScenario{
|
|||||||
document: mergeDocSample,
|
document: mergeDocSample,
|
||||||
expression: `.foobar | [...]`,
|
expression: `.foobar | [...]`,
|
||||||
expected: []string{
|
expected: []string{
|
||||||
"D0, P[], (!!seq)::- c: foobar_c\n !!merge <<: *foo\n thing: foobar_thing\n- c\n- foobar_c\n- !!merge <<\n- *foo\n- thing\n- foobar_thing\n",
|
"D0, P[foobar], (!!seq)::- c: foobar_c\n !!merge <<: *foo\n thing: foobar_thing\n- c\n- foobar_c\n- !!merge <<\n- *foo\n- thing\n- foobar_thing\n",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -96,8 +96,8 @@ func traverseArrayOperator(d *dataTreeNavigator, context Context, expressionNode
|
|||||||
}
|
}
|
||||||
prefs := traversePreferences{}
|
prefs := traversePreferences{}
|
||||||
|
|
||||||
if expressionNode.Rhs.Rhs != nil && expressionNode.Rhs.Rhs.Operation.Preferences != nil {
|
if expressionNode.Operation.Preferences != nil {
|
||||||
prefs = expressionNode.Rhs.Rhs.Operation.Preferences.(traversePreferences)
|
prefs = expressionNode.Operation.Preferences.(traversePreferences)
|
||||||
}
|
}
|
||||||
var indicesToTraverse = rhs.MatchingNodes.Front().Value.(*CandidateNode).Node.Content
|
var indicesToTraverse = rhs.MatchingNodes.Front().Value.(*CandidateNode).Node.Content
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user