Fixed boolean ops

This commit is contained in:
Mike Farah 2020-11-20 15:29:53 +11:00
parent bc87aca8d7
commit f03005f86d
3 changed files with 41 additions and 22 deletions

View File

@ -6,7 +6,7 @@ Which will assign the LHS node values to the RHS node values. The RHS expression
### relative form: `|=`
This will do a similar thing to the plain form, however, the RHS expression is run against _the LHS nodes_. This is useful for updating values based on old values, e.g. increment.
## Examples
### Update parent to be the child value
### Update node to be the child value
Given a sample.yml file of:
```yaml
a:
@ -23,7 +23,7 @@ a:
g: foof
```
### Update to be the sibling value
### Update node to be the sibling value
Given a sample.yml file of:
```yaml
a:

View File

@ -3,7 +3,7 @@ package yqlib
import (
"container/list"
"gopkg.in/yaml.v3"
yaml "gopkg.in/yaml.v3"
)
func isTruthy(c *CandidateNode) (bool, error) {
@ -25,9 +25,42 @@ func isTruthy(c *CandidateNode) (bool, error) {
type boolOp func(bool, bool) bool
func performBoolOp(results *list.List, lhs *list.List, rhs *list.List, op boolOp) error {
for lhsChild := lhs.Front(); lhsChild != nil; lhsChild = lhsChild.Next() {
lhsCandidate := lhsChild.Value.(*CandidateNode)
lhsTrue, errDecoding := isTruthy(lhsCandidate)
if errDecoding != nil {
return errDecoding
}
for rhsChild := rhs.Front(); rhsChild != nil; rhsChild = rhsChild.Next() {
rhsCandidate := rhsChild.Value.(*CandidateNode)
rhsTrue, errDecoding := isTruthy(rhsCandidate)
if errDecoding != nil {
return errDecoding
}
boolResult := createBooleanCandidate(lhsCandidate, op(lhsTrue, rhsTrue))
results.PushBack(boolResult)
}
}
return nil
}
func booleanOp(d *dataTreeNavigator, matchingNodes *list.List, pathNode *PathTreeNode, op boolOp) (*list.List, error) {
var results = list.New()
if matchingNodes.Len() == 0 {
lhs, err := d.GetMatchingNodes(list.New(), pathNode.Lhs)
if err != nil {
return nil, err
}
rhs, err := d.GetMatchingNodes(list.New(), pathNode.Rhs)
if err != nil {
return nil, err
}
return results, performBoolOp(results, lhs, rhs, op)
}
for el := matchingNodes.Front(); el != nil; el = el.Next() {
candidate := el.Value.(*CandidateNode)
lhs, err := d.GetMatchingNodes(nodeToMap(candidate), pathNode.Lhs)
@ -39,23 +72,9 @@ func booleanOp(d *dataTreeNavigator, matchingNodes *list.List, pathNode *PathTre
return nil, err
}
for lhsChild := lhs.Front(); lhsChild != nil; lhsChild = lhsChild.Next() {
lhsCandidate := lhsChild.Value.(*CandidateNode)
lhsTrue, errDecoding := isTruthy(lhsCandidate)
if errDecoding != nil {
return nil, errDecoding
}
for rhsChild := rhs.Front(); rhsChild != nil; rhsChild = rhsChild.Next() {
rhsCandidate := rhsChild.Value.(*CandidateNode)
rhsTrue, errDecoding := isTruthy(rhsCandidate)
if errDecoding != nil {
return nil, errDecoding
}
boolResult := createBooleanCandidate(lhsCandidate, op(lhsTrue, rhsTrue))
results.PushBack(boolResult)
}
err = performBoolOp(results, lhs, rhs, op)
if err != nil {
return nil, err
}
}

View File

@ -24,8 +24,8 @@ var booleanOperatorScenarios = []expressionScenario{
description: "Matching nodes with select, equals and or",
expression: `.[] | select(.a == "cat" or .b == "dog")`,
expected: []string{
"D0, P[], (!!map)::{a: bird, b: dog}\n",
"D0, P[], (!!map)::{a: cat, b: fly}\n",
"D0, P[0], (!!map)::{a: bird, b: dog}\n",
"D0, P[2], (!!map)::{a: cat, b: fly}\n",
},
},
{