mirror of
https://github.com/mikefarah/yq.git
synced 2024-11-13 22:38:04 +00:00
Fixed boolean op with empty context issue
This commit is contained in:
parent
25d0787011
commit
37f3e21970
@ -93,3 +93,31 @@ will output
|
||||
true
|
||||
```
|
||||
|
||||
## Non exisitant key doesn't equal a value
|
||||
Given a sample.yml file of:
|
||||
```yaml
|
||||
a: frog
|
||||
```
|
||||
then
|
||||
```bash
|
||||
yq eval 'select(.b != "thing")' sample.yml
|
||||
```
|
||||
will output
|
||||
```yaml
|
||||
a: frog
|
||||
```
|
||||
|
||||
## Two non existant keys are equal
|
||||
Given a sample.yml file of:
|
||||
```yaml
|
||||
a: frog
|
||||
```
|
||||
then
|
||||
```bash
|
||||
yq eval 'select(.b == .c)' sample.yml
|
||||
```
|
||||
will output
|
||||
```yaml
|
||||
a: frog
|
||||
```
|
||||
|
||||
|
@ -27,20 +27,37 @@ type boolOp func(bool, bool) bool
|
||||
|
||||
func performBoolOp(op boolOp) func(d *dataTreeNavigator, context Context, lhs *CandidateNode, rhs *CandidateNode) (*CandidateNode, error) {
|
||||
return func(d *dataTreeNavigator, context Context, lhs *CandidateNode, rhs *CandidateNode) (*CandidateNode, error) {
|
||||
lhs.Node = unwrapDoc(lhs.Node)
|
||||
rhs.Node = unwrapDoc(rhs.Node)
|
||||
owner := lhs
|
||||
|
||||
lhsTrue, errDecoding := isTruthy(lhs)
|
||||
if errDecoding != nil {
|
||||
return nil, errDecoding
|
||||
if lhs == nil && rhs == nil {
|
||||
owner = &CandidateNode{}
|
||||
} else if lhs == nil {
|
||||
owner = rhs
|
||||
}
|
||||
|
||||
rhsTrue, errDecoding := isTruthy(rhs)
|
||||
if errDecoding != nil {
|
||||
return nil, errDecoding
|
||||
}
|
||||
var errDecoding error
|
||||
lhsTrue := false
|
||||
if lhs != nil {
|
||||
lhs.Node = unwrapDoc(lhs.Node)
|
||||
lhsTrue, errDecoding = isTruthy(lhs)
|
||||
|
||||
return createBooleanCandidate(lhs, op(lhsTrue, rhsTrue)), nil
|
||||
if errDecoding != nil {
|
||||
return nil, errDecoding
|
||||
}
|
||||
}
|
||||
log.Debugf("-- lhsTrue", lhsTrue)
|
||||
|
||||
rhsTrue := false
|
||||
if rhs != nil {
|
||||
rhs.Node = unwrapDoc(rhs.Node)
|
||||
rhsTrue, errDecoding = isTruthy(rhs)
|
||||
if errDecoding != nil {
|
||||
return nil, errDecoding
|
||||
}
|
||||
}
|
||||
log.Debugf("-- rhsTrue", rhsTrue)
|
||||
|
||||
return createBooleanCandidate(owner, op(lhsTrue, rhsTrue)), nil
|
||||
}
|
||||
}
|
||||
|
||||
@ -48,8 +65,9 @@ func orOperator(d *dataTreeNavigator, context Context, expressionNode *Expressio
|
||||
log.Debugf("-- orOp")
|
||||
return crossFunction(d, context, expressionNode, performBoolOp(
|
||||
func(b1 bool, b2 bool) bool {
|
||||
log.Debugf("-- peformingOrOp with %v and %v", b1, b2)
|
||||
return b1 || b2
|
||||
}), false)
|
||||
}), true)
|
||||
}
|
||||
|
||||
func andOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
|
||||
@ -57,7 +75,7 @@ func andOperator(d *dataTreeNavigator, context Context, expressionNode *Expressi
|
||||
return crossFunction(d, context, expressionNode, performBoolOp(
|
||||
func(b1 bool, b2 bool) bool {
|
||||
return b1 && b2
|
||||
}), false)
|
||||
}), true)
|
||||
}
|
||||
|
||||
func notOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
|
||||
|
@ -12,6 +12,22 @@ var booleanOperatorScenarios = []expressionScenario{
|
||||
"D0, P[], (!!bool)::true\n",
|
||||
},
|
||||
},
|
||||
{
|
||||
skipDoc: true,
|
||||
document: "b: hi",
|
||||
expression: `select(.a or .b)`,
|
||||
expected: []string{
|
||||
"D0, P[], (doc)::b: hi\n",
|
||||
},
|
||||
},
|
||||
{
|
||||
skipDoc: true,
|
||||
document: "b: hi",
|
||||
expression: `select((.a and .b) | not)`,
|
||||
expected: []string{
|
||||
"D0, P[], (doc)::b: hi\n",
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "AND example",
|
||||
expression: `true and false`,
|
||||
|
@ -4,13 +4,22 @@ import "gopkg.in/yaml.v3"
|
||||
|
||||
func equalsOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
|
||||
log.Debugf("-- equalsOperation")
|
||||
return crossFunction(d, context, expressionNode, isEquals(false), false)
|
||||
return crossFunction(d, context, expressionNode, isEquals(false), true)
|
||||
}
|
||||
|
||||
func isEquals(flip bool) func(d *dataTreeNavigator, context Context, lhs *CandidateNode, rhs *CandidateNode) (*CandidateNode, error) {
|
||||
return func(d *dataTreeNavigator, context Context, lhs *CandidateNode, rhs *CandidateNode) (*CandidateNode, error) {
|
||||
value := false
|
||||
|
||||
if lhs == nil && rhs == nil {
|
||||
owner := &CandidateNode{}
|
||||
return createBooleanCandidate(owner, !flip), nil
|
||||
} else if lhs == nil {
|
||||
return createBooleanCandidate(rhs, flip), nil
|
||||
} else if rhs == nil {
|
||||
return createBooleanCandidate(lhs, flip), nil
|
||||
}
|
||||
|
||||
lhsNode := unwrapDoc(lhs.Node)
|
||||
rhsNode := unwrapDoc(rhs.Node)
|
||||
|
||||
@ -29,5 +38,5 @@ func isEquals(flip bool) func(d *dataTreeNavigator, context Context, lhs *Candid
|
||||
|
||||
func notEqualsOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
|
||||
log.Debugf("-- equalsOperation")
|
||||
return crossFunction(d, context, expressionNode, isEquals(true), false)
|
||||
return crossFunction(d, context, expressionNode, isEquals(true), true)
|
||||
}
|
||||
|
@ -87,6 +87,22 @@ var equalsOperatorScenarios = []expressionScenario{
|
||||
"D0, P[], (!!bool)::true\n",
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Non exisitant key doesn't equal a value",
|
||||
document: "a: frog",
|
||||
expression: `select(.b != "thing")`,
|
||||
expected: []string{
|
||||
"D0, P[], (doc)::a: frog\n",
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Two non existant keys are equal",
|
||||
document: "a: frog",
|
||||
expression: `select(.b == .c)`,
|
||||
expected: []string{
|
||||
"D0, P[], (doc)::a: frog\n",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
func TestEqualOperatorScenarios(t *testing.T) {
|
||||
|
@ -14,6 +14,16 @@ var selectOperatorScenarios = []expressionScenario{
|
||||
"D0, P[1], (!!str)::goat\n",
|
||||
},
|
||||
},
|
||||
{
|
||||
skipDoc: true,
|
||||
document: "a: hello",
|
||||
document2: "b: world",
|
||||
expression: `select(.a == "hello" or .b == "world")`,
|
||||
expected: []string{
|
||||
"D0, P[], (doc)::a: hello\n",
|
||||
"D0, P[], (doc)::b: world\n",
|
||||
},
|
||||
},
|
||||
{
|
||||
skipDoc: true,
|
||||
document: `[{animal: cat, legs: {cool: true}}, {animal: fish}]`,
|
||||
|
Loading…
Reference in New Issue
Block a user