mirror of
https://github.com/mikefarah/yq.git
synced 2026-07-08 06:45: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 {
|
if expressionNode.Operation.Preferences != nil {
|
||||||
prefs = expressionNode.Operation.Preferences.(traversePreferences)
|
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
|
var indicesToTraverse = rhs.MatchingNodes.Front().Value.(*CandidateNode).Content
|
||||||
|
|
||||||
log.Debugf("indicesToTraverse %v", len(indicesToTraverse))
|
log.Debugf("indicesToTraverse %v", len(indicesToTraverse))
|
||||||
|
|||||||
@ -132,6 +132,38 @@ var badTraversePathOperatorScenarios = []expressionScenario{
|
|||||||
}
|
}
|
||||||
|
|
||||||
var traversePathOperatorScenarios = []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,
|
skipDoc: true,
|
||||||
description: "strange map with key but no value",
|
description: "strange map with key but no value",
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user