mirror of
https://github.com/mikefarah/yq.git
synced 2026-10-11 21:39:52 +00:00
fix: apply ireduce per pipeline input like jq reduce (#2869)
match(...) | (.captures[] as $c ireduce (...)) folded every match's captures into one accumulator, so only the last object remained. jq reduce runs once per input. Use the same EvaluateTogether split as `as` and collect; eval-all file merges are unchanged. Fixes #2859
This commit is contained in:
@@ -21,6 +21,32 @@ func reduceOperator(d *dataTreeNavigator, context Context, expressionNode *Expre
|
||||
return Context{}, fmt.Errorf("reduce must be given a block, got %v instead", expressionNode.RHS.Operation.OperationType.Type)
|
||||
}
|
||||
|
||||
// Same EvaluateTogether split as `as` / collect / crossFunction:
|
||||
// file documents are reduced together (eval-all merge), while
|
||||
// pipeline results such as match(...) are reduced per input, like jq.
|
||||
var evaluateAllTogether = true
|
||||
for matchEl := context.MatchingNodes.Front(); matchEl != nil; matchEl = matchEl.Next() {
|
||||
evaluateAllTogether = evaluateAllTogether && matchEl.Value.(*CandidateNode).EvaluateTogether
|
||||
if !evaluateAllTogether {
|
||||
break
|
||||
}
|
||||
}
|
||||
if evaluateAllTogether {
|
||||
return reduceOperatorSingle(d, context, expressionNode)
|
||||
}
|
||||
|
||||
results := list.New()
|
||||
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
|
||||
result, err := reduceOperatorSingle(d, context.SingleChildContext(el.Value.(*CandidateNode)), expressionNode)
|
||||
if err != nil {
|
||||
return Context{}, err
|
||||
}
|
||||
results.PushBackList(result.MatchingNodes)
|
||||
}
|
||||
return context.ChildContext(results), nil
|
||||
}
|
||||
|
||||
func reduceOperatorSingle(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
|
||||
arrayExpNode := expressionNode.LHS.LHS
|
||||
array, err := d.GetMatchingNodes(context, arrayExpNode)
|
||||
|
||||
|
||||
@@ -30,6 +30,14 @@ var reduceOperatorScenarios = []expressionScenario{
|
||||
"D0, P[], (!!map)::Cathy: apples\nBob: bananas\n",
|
||||
},
|
||||
},
|
||||
{
|
||||
skipDoc: true,
|
||||
description: "Issue 2859: match then ireduce .captures[] matches jq reduce / capture",
|
||||
expression: `"\"a\"=\"b\" \"x\"=\"y\"" | [match("\"(?<key>.*?)\"=\"(?<value>.*?)\""; "g") | (.captures[] as $capture ireduce ({}; .[$capture.name] = $capture.string))]`,
|
||||
expected: []string{
|
||||
"D0, P[], (!!seq)::- key: a\n value: b\n- key: x\n value: y\n",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
func TestReduceOperatorScenarios(t *testing.T) {
|
||||
|
||||
Reference in New Issue
Block a user