mirror of
https://github.com/mikefarah/yq.git
synced 2026-07-07 14:25:38 +00:00
fix: traverse array with streaming indices from variable binding
When streaming values (e.g. from keys[]) pipe into an array traversal like $o[.], only the first streaming index was used. The RHS collect expression produces a separate SequenceNode per streaming value when EvaluateTogether is false. The existing code at line 126 only took the first SequenceNode, discarding the rest. When the LHS is a single bound variable and the RHS has multiple index sets, traverse each set separately. Fixes #2593
This commit is contained in:
parent
3b2423e871
commit
f4f77089ff
@ -123,6 +123,27 @@ func traverseArrayOperator(d *dataTreeNavigator, context Context, expressionNode
|
||||
if expressionNode.Operation.Preferences != nil {
|
||||
prefs = expressionNode.Operation.Preferences.(traversePreferences)
|
||||
}
|
||||
|
||||
// When streaming values produce per-value index sets in the RHS and the LHS
|
||||
// is a single node (e.g. a bound variable), traverse the LHS with each
|
||||
// index set separately. Without this, only the first set of indices is used
|
||||
// and the rest are silently dropped.
|
||||
if rhs.MatchingNodes.Len() > 1 && lhs.MatchingNodes.Len() < rhs.MatchingNodes.Len() {
|
||||
var allResults = list.New()
|
||||
for el := rhs.MatchingNodes.Front(); el != nil; el = el.Next() {
|
||||
seqNode := el.Value.(*CandidateNode)
|
||||
if seqNode.Kind != SequenceNode {
|
||||
continue
|
||||
}
|
||||
result, err := traverseNodesWithArrayIndices(lhs, seqNode.Content, prefs)
|
||||
if err != nil {
|
||||
return Context{}, err
|
||||
}
|
||||
allResults.PushBackList(result.MatchingNodes)
|
||||
}
|
||||
return context.ChildContext(allResults), nil
|
||||
}
|
||||
|
||||
var indicesToTraverse = rhs.MatchingNodes.Front().Value.(*CandidateNode).Content
|
||||
|
||||
log.Debugf("indicesToTraverse %v", len(indicesToTraverse))
|
||||
|
||||
@ -132,6 +132,38 @@ var badTraversePathOperatorScenarios = []expressionScenario{
|
||||
}
|
||||
|
||||
var traversePathOperatorScenarios = []expressionScenario{
|
||||
{
|
||||
skipDoc: true,
|
||||
description: "traverse array with streaming indices from keys",
|
||||
document: `["a","b"]`,
|
||||
expression: `. as $o | keys[] | $o[.]`,
|
||||
expected: []string{
|
||||
"D0, P[0], (!!str)::a\n",
|
||||
"D0, P[1], (!!str)::b\n",
|
||||
},
|
||||
},
|
||||
{
|
||||
skipDoc: true,
|
||||
description: "traverse map with streaming indices from keys",
|
||||
document: `{x: "a", y: "b"}`,
|
||||
expression: `. as $o | keys[] | $o[.]`,
|
||||
expected: []string{
|
||||
"D0, P[x], (!!str)::a\n",
|
||||
"D0, P[y], (!!str)::b\n",
|
||||
},
|
||||
},
|
||||
{
|
||||
skipDoc: true,
|
||||
description: "traverse longer array with streaming indices from keys",
|
||||
document: `["a","b","c","d"]`,
|
||||
expression: `. as $o | keys[] | $o[.]`,
|
||||
expected: []string{
|
||||
"D0, P[0], (!!str)::a\n",
|
||||
"D0, P[1], (!!str)::b\n",
|
||||
"D0, P[2], (!!str)::c\n",
|
||||
"D0, P[3], (!!str)::d\n",
|
||||
},
|
||||
},
|
||||
{
|
||||
skipDoc: true,
|
||||
description: "strange map with key but no value",
|
||||
|
||||
Loading…
Reference in New Issue
Block a user