diff --git a/pkg/yqlib/operator_traverse_path.go b/pkg/yqlib/operator_traverse_path.go index 1ed0757246..6ed991cc85 100644 --- a/pkg/yqlib/operator_traverse_path.go +++ b/pkg/yqlib/operator_traverse_path.go @@ -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)) diff --git a/pkg/yqlib/operator_traverse_path_test.go b/pkg/yqlib/operator_traverse_path_test.go index 6b2d63e3e8..9e0d408247 100644 --- a/pkg/yqlib/operator_traverse_path_test.go +++ b/pkg/yqlib/operator_traverse_path_test.go @@ -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",