mirror of
https://github.com/mikefarah/yq.git
synced 2026-07-02 02:11:39 +00:00
Merge 0cc5c19843 into 8e2c9b612d
This commit is contained in:
commit
493a020d18
@ -111,10 +111,10 @@ func traverseArrayOperator(d *dataTreeNavigator, context Context, expressionNode
|
||||
return Context{}, err
|
||||
}
|
||||
|
||||
// rhs is a collect expression that will yield indices to retrieve of the arrays
|
||||
|
||||
// rhs is a collect expression that yields the indices to retrieve. It is
|
||||
// evaluated over the whole context, producing one index set per incoming
|
||||
// candidate.
|
||||
rhs, err := d.GetMatchingNodes(context.ReadOnlyClone(), expressionNode.RHS)
|
||||
|
||||
if err != nil {
|
||||
return Context{}, err
|
||||
}
|
||||
@ -123,16 +123,37 @@ func traverseArrayOperator(d *dataTreeNavigator, context Context, expressionNode
|
||||
if expressionNode.Operation.Preferences != nil {
|
||||
prefs = expressionNode.Operation.Preferences.(traversePreferences)
|
||||
}
|
||||
var indicesToTraverse = rhs.MatchingNodes.Front().Value.(*CandidateNode).Content
|
||||
|
||||
log.Debugf("indicesToTraverse %v", len(indicesToTraverse))
|
||||
|
||||
//now we traverse the result of the lhs against the indices we found
|
||||
result, err := traverseNodesWithArrayIndices(lhs, indicesToTraverse, prefs)
|
||||
if err != nil {
|
||||
return Context{}, err
|
||||
results := list.New()
|
||||
if lhs.MatchingNodes.Len() == rhs.MatchingNodes.Len() {
|
||||
// One index set per LHS node (both derive from the same context):
|
||||
// traverse each LHS node with its own index set. Previously only the
|
||||
// first index set was used, so a context-dependent index like `$o[.]`
|
||||
// over a `keys[]` stream dropped every match but the first (#2593).
|
||||
rhsEl := rhs.MatchingNodes.Front()
|
||||
for lhsEl := lhs.MatchingNodes.Front(); lhsEl != nil; lhsEl = lhsEl.Next() {
|
||||
indicesToTraverse := rhsEl.Value.(*CandidateNode).Content
|
||||
result, err := traverseNodesWithArrayIndices(context.SingleChildContext(lhsEl.Value.(*CandidateNode)), indicesToTraverse, prefs)
|
||||
if err != nil {
|
||||
return Context{}, err
|
||||
}
|
||||
results.PushBackList(result.MatchingNodes)
|
||||
rhsEl = rhsEl.Next()
|
||||
}
|
||||
} else {
|
||||
// LHS collapsed to a single node (e.g. a variable) while the index
|
||||
// varies per candidate: traverse the LHS against every index set.
|
||||
for rhsEl := rhs.MatchingNodes.Front(); rhsEl != nil; rhsEl = rhsEl.Next() {
|
||||
indicesToTraverse := rhsEl.Value.(*CandidateNode).Content
|
||||
result, err := traverseNodesWithArrayIndices(lhs, indicesToTraverse, prefs)
|
||||
if err != nil {
|
||||
return Context{}, err
|
||||
}
|
||||
results.PushBackList(result.MatchingNodes)
|
||||
}
|
||||
}
|
||||
return context.ChildContext(result.MatchingNodes), nil
|
||||
|
||||
return context.ChildContext(results), nil
|
||||
}
|
||||
|
||||
func traverseNodesWithArrayIndices(context Context, indicesToTraverse []*CandidateNode, prefs traversePreferences) (Context, error) {
|
||||
|
||||
@ -675,6 +675,27 @@ var traversePathOperatorScenarios = []expressionScenario{
|
||||
expression: ". = (.x = 1)",
|
||||
expectedError: "alias cycle detected",
|
||||
},
|
||||
{
|
||||
// Regression test for https://github.com/mikefarah/yq/issues/2593
|
||||
// A context-dependent index (here the streamed key) must be applied
|
||||
// per candidate; previously only the first index was used.
|
||||
skipDoc: true,
|
||||
document: `["a","b"]`,
|
||||
expression: `. as $o | keys[] | $o[.]`,
|
||||
expected: []string{
|
||||
"D0, P[0], (!!str)::a\n",
|
||||
"D0, P[1], (!!str)::b\n",
|
||||
},
|
||||
},
|
||||
{
|
||||
skipDoc: true,
|
||||
document: `{"x": 1, "y": 2}`,
|
||||
expression: `. as $o | keys[] | $o[.]`,
|
||||
expected: []string{
|
||||
"D0, P[x], (!!int)::1\n",
|
||||
"D0, P[y], (!!int)::2\n",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
func TestTraversePathOperatorScenarios(t *testing.T) {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user