mirror of
https://github.com/mikefarah/yq.git
synced 2025-01-23 22:25:42 +00:00
Fixed alternative operator when LHS has empty matches
This commit is contained in:
parent
095f921f62
commit
25e0a824c5
@ -39,7 +39,7 @@ func toNodes(candidate *CandidateNode) []*yaml.Node {
|
|||||||
func addOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
|
func addOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
|
||||||
log.Debugf("Add operator")
|
log.Debugf("Add operator")
|
||||||
|
|
||||||
return crossFunction(d, context, expressionNode, add)
|
return crossFunction(d, context, expressionNode, add, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
func add(d *dataTreeNavigator, context Context, lhs *CandidateNode, rhs *CandidateNode) (*CandidateNode, error) {
|
func add(d *dataTreeNavigator, context Context, lhs *CandidateNode, rhs *CandidateNode) (*CandidateNode, error) {
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
package yqlib
|
package yqlib
|
||||||
|
|
||||||
// corssFunction no matches
|
|
||||||
// can boolean use crossfunction
|
|
||||||
|
|
||||||
func alternativeOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
|
func alternativeOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
|
||||||
log.Debugf("-- alternative")
|
log.Debugf("-- alternative")
|
||||||
return crossFunction(d, context, expressionNode, alternativeFunc)
|
return crossFunction(d, context, expressionNode, alternativeFunc, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
func alternativeFunc(d *dataTreeNavigator, context Context, lhs *CandidateNode, rhs *CandidateNode) (*CandidateNode, error) {
|
func alternativeFunc(d *dataTreeNavigator, context Context, lhs *CandidateNode, rhs *CandidateNode) (*CandidateNode, error) {
|
||||||
|
if lhs == nil {
|
||||||
|
return rhs, nil
|
||||||
|
}
|
||||||
lhs.Node = unwrapDoc(lhs.Node)
|
lhs.Node = unwrapDoc(lhs.Node)
|
||||||
rhs.Node = unwrapDoc(rhs.Node)
|
rhs.Node = unwrapDoc(rhs.Node)
|
||||||
log.Debugf("Alternative LHS: %v", lhs.Node.Tag)
|
log.Debugf("Alternative LHS: %v", lhs.Node.Tag)
|
||||||
|
@ -13,6 +13,14 @@ var alternativeOperatorScenarios = []expressionScenario{
|
|||||||
"D0, P[a], (!!str)::bridge\n",
|
"D0, P[a], (!!str)::bridge\n",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
expression: `select(tag == "seq") // "cat"`,
|
||||||
|
skipDoc: true,
|
||||||
|
document: `a: frog`,
|
||||||
|
expected: []string{
|
||||||
|
"D0, P[], (!!str)::cat\n",
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
description: "LHS is not defined",
|
description: "LHS is not defined",
|
||||||
expression: `.a // "hello"`,
|
expression: `.a // "hello"`,
|
||||||
|
@ -49,7 +49,7 @@ func orOperator(d *dataTreeNavigator, context Context, expressionNode *Expressio
|
|||||||
return crossFunction(d, context, expressionNode, performBoolOp(
|
return crossFunction(d, context, expressionNode, performBoolOp(
|
||||||
func(b1 bool, b2 bool) bool {
|
func(b1 bool, b2 bool) bool {
|
||||||
return b1 || b2
|
return b1 || b2
|
||||||
}))
|
}), false)
|
||||||
}
|
}
|
||||||
|
|
||||||
func andOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
|
func andOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
|
||||||
@ -57,7 +57,7 @@ func andOperator(d *dataTreeNavigator, context Context, expressionNode *Expressi
|
|||||||
return crossFunction(d, context, expressionNode, performBoolOp(
|
return crossFunction(d, context, expressionNode, performBoolOp(
|
||||||
func(b1 bool, b2 bool) bool {
|
func(b1 bool, b2 bool) bool {
|
||||||
return b1 && b2
|
return b1 && b2
|
||||||
}))
|
}), false)
|
||||||
}
|
}
|
||||||
|
|
||||||
func notOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
|
func notOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
|
||||||
|
@ -62,7 +62,7 @@ func sequenceFor(d *dataTreeNavigator, context Context, matchingNode *CandidateN
|
|||||||
}
|
}
|
||||||
|
|
||||||
return &CandidateNode{Node: &node, Document: document, Path: path}, nil
|
return &CandidateNode{Node: &node, Document: document, Path: path}, nil
|
||||||
})
|
}, false)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -4,7 +4,7 @@ import "gopkg.in/yaml.v3"
|
|||||||
|
|
||||||
func equalsOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
|
func equalsOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
|
||||||
log.Debugf("-- equalsOperation")
|
log.Debugf("-- equalsOperation")
|
||||||
return crossFunction(d, context, expressionNode, isEquals(false))
|
return crossFunction(d, context, expressionNode, isEquals(false), false)
|
||||||
}
|
}
|
||||||
|
|
||||||
func isEquals(flip bool) func(d *dataTreeNavigator, context Context, lhs *CandidateNode, rhs *CandidateNode) (*CandidateNode, error) {
|
func isEquals(flip bool) func(d *dataTreeNavigator, context Context, lhs *CandidateNode, rhs *CandidateNode) (*CandidateNode, error) {
|
||||||
@ -29,5 +29,5 @@ func isEquals(flip bool) func(d *dataTreeNavigator, context Context, lhs *Candid
|
|||||||
|
|
||||||
func notEqualsOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
|
func notEqualsOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
|
||||||
log.Debugf("-- equalsOperation")
|
log.Debugf("-- equalsOperation")
|
||||||
return crossFunction(d, context, expressionNode, isEquals(true))
|
return crossFunction(d, context, expressionNode, isEquals(true), false)
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@ type multiplyPreferences struct {
|
|||||||
|
|
||||||
func multiplyOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
|
func multiplyOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
|
||||||
log.Debugf("-- MultiplyOperator")
|
log.Debugf("-- MultiplyOperator")
|
||||||
return crossFunction(d, context, expressionNode, multiply(expressionNode.Operation.Preferences.(multiplyPreferences)))
|
return crossFunction(d, context, expressionNode, multiply(expressionNode.Operation.Preferences.(multiplyPreferences)), false)
|
||||||
}
|
}
|
||||||
|
|
||||||
func multiply(preferences multiplyPreferences) func(d *dataTreeNavigator, context Context, lhs *CandidateNode, rhs *CandidateNode) (*CandidateNode, error) {
|
func multiply(preferences multiplyPreferences) func(d *dataTreeNavigator, context Context, lhs *CandidateNode, rhs *CandidateNode) (*CandidateNode, error) {
|
||||||
|
@ -25,7 +25,7 @@ func subtractAssignOperator(d *dataTreeNavigator, context Context, expressionNod
|
|||||||
func subtractOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
|
func subtractOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
|
||||||
log.Debugf("Subtract operator")
|
log.Debugf("Subtract operator")
|
||||||
|
|
||||||
return crossFunction(d, context, expressionNode, subtract)
|
return crossFunction(d, context, expressionNode, subtract, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
func subtract(d *dataTreeNavigator, context Context, lhs *CandidateNode, rhs *CandidateNode) (*CandidateNode, error) {
|
func subtract(d *dataTreeNavigator, context Context, lhs *CandidateNode, rhs *CandidateNode) (*CandidateNode, error) {
|
||||||
|
@ -24,7 +24,20 @@ func emptyOperator(d *dataTreeNavigator, context Context, expressionNode *Expres
|
|||||||
|
|
||||||
type crossFunctionCalculation func(d *dataTreeNavigator, context Context, lhs *CandidateNode, rhs *CandidateNode) (*CandidateNode, error)
|
type crossFunctionCalculation func(d *dataTreeNavigator, context Context, lhs *CandidateNode, rhs *CandidateNode) (*CandidateNode, error)
|
||||||
|
|
||||||
func doCrossFunc(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode, calculation crossFunctionCalculation) (Context, error) {
|
func resultsForRhs(d *dataTreeNavigator, context Context, lhsCandidate *CandidateNode, rhs Context, calculation crossFunctionCalculation, results *list.List) error {
|
||||||
|
for rightEl := rhs.MatchingNodes.Front(); rightEl != nil; rightEl = rightEl.Next() {
|
||||||
|
log.Debugf("Applying calc")
|
||||||
|
rhsCandidate := rightEl.Value.(*CandidateNode)
|
||||||
|
resultCandidate, err := calculation(d, context, lhsCandidate, rhsCandidate)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
results.PushBack(resultCandidate)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func doCrossFunc(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode, calculation crossFunctionCalculation, calcWhenEmpty bool) (Context, error) {
|
||||||
var results = list.New()
|
var results = list.New()
|
||||||
lhs, err := d.GetMatchingNodes(context, expressionNode.Lhs)
|
lhs, err := d.GetMatchingNodes(context, expressionNode.Lhs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -38,24 +51,33 @@ func doCrossFunc(d *dataTreeNavigator, context Context, expressionNode *Expressi
|
|||||||
return Context{}, err
|
return Context{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
for el := lhs.MatchingNodes.Front(); el != nil; el = el.Next() {
|
if calcWhenEmpty && lhs.MatchingNodes.Len() == 0 {
|
||||||
lhsCandidate := el.Value.(*CandidateNode)
|
if rhs.MatchingNodes.Len() == 0 {
|
||||||
|
resultCandidate, err := calculation(d, context, nil, nil)
|
||||||
for rightEl := rhs.MatchingNodes.Front(); rightEl != nil; rightEl = rightEl.Next() {
|
|
||||||
log.Debugf("Applying calc")
|
|
||||||
rhsCandidate := rightEl.Value.(*CandidateNode)
|
|
||||||
resultCandidate, err := calculation(d, context, lhsCandidate, rhsCandidate)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return Context{}, err
|
return Context{}, err
|
||||||
}
|
}
|
||||||
results.PushBack(resultCandidate)
|
results.PushBack(resultCandidate)
|
||||||
}
|
}
|
||||||
|
err := resultsForRhs(d, context, nil, rhs, calculation, results)
|
||||||
|
if err != nil {
|
||||||
|
return Context{}, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for el := lhs.MatchingNodes.Front(); el != nil; el = el.Next() {
|
||||||
|
lhsCandidate := el.Value.(*CandidateNode)
|
||||||
|
|
||||||
|
err := resultsForRhs(d, context, lhsCandidate, rhs, calculation, results)
|
||||||
|
if err != nil {
|
||||||
|
return Context{}, err
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
return context.ChildContext(results), nil
|
return context.ChildContext(results), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func crossFunction(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode, calculation crossFunctionCalculation) (Context, error) {
|
func crossFunction(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode, calculation crossFunctionCalculation, calcWhenEmpty bool) (Context, error) {
|
||||||
var results = list.New()
|
var results = list.New()
|
||||||
|
|
||||||
var evaluateAllTogether = true
|
var evaluateAllTogether = true
|
||||||
@ -66,11 +88,11 @@ func crossFunction(d *dataTreeNavigator, context Context, expressionNode *Expres
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if evaluateAllTogether {
|
if evaluateAllTogether {
|
||||||
return doCrossFunc(d, context, expressionNode, calculation)
|
return doCrossFunc(d, context, expressionNode, calculation, calcWhenEmpty)
|
||||||
}
|
}
|
||||||
|
|
||||||
for matchEl := context.MatchingNodes.Front(); matchEl != nil; matchEl = matchEl.Next() {
|
for matchEl := context.MatchingNodes.Front(); matchEl != nil; matchEl = matchEl.Next() {
|
||||||
innerResults, err := doCrossFunc(d, context.SingleChildContext(matchEl.Value.(*CandidateNode)), expressionNode, calculation)
|
innerResults, err := doCrossFunc(d, context.SingleChildContext(matchEl.Value.(*CandidateNode)), expressionNode, calculation, calcWhenEmpty)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return Context{}, err
|
return Context{}, err
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user