Fixed handling of null expressions in equals op

This commit is contained in:
Mike Farah 2021-05-16 12:16:10 +10:00
parent 7b52c5fe0e
commit 5340ed0ad3
4 changed files with 53 additions and 14 deletions

View File

@ -10,14 +10,26 @@ func equalsOperator(d *dataTreeNavigator, context Context, expressionNode *Expre
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) {
return 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 value := false
log.Debugf("-- isEquals cross function")
if lhs == nil && rhs == nil { if lhs == nil && rhs == nil {
owner := &CandidateNode{} owner := &CandidateNode{}
return createBooleanCandidate(owner, !flip), nil return createBooleanCandidate(owner, !flip), nil
} else if lhs == nil { } else if lhs == nil {
return createBooleanCandidate(rhs, flip), nil log.Debugf("lhs nil, but rhs is not")
rhsNode := unwrapDoc(rhs.Node)
value := rhsNode.Tag == "!!null"
if flip {
value = !value
}
return createBooleanCandidate(rhs, value), nil
} else if rhs == nil { } else if rhs == nil {
return createBooleanCandidate(lhs, flip), nil log.Debugf("lhs not nil, but rhs is")
lhsNode := unwrapDoc(lhs.Node)
value := lhsNode.Tag == "!!null"
if flip {
value = !value
}
return createBooleanCandidate(lhs, value), nil
} }
lhsNode := unwrapDoc(lhs.Node) lhsNode := unwrapDoc(lhs.Node)
@ -37,6 +49,6 @@ 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("-- notEqualsOperator")
return crossFunction(d, context, expressionNode, isEquals(true), true) return crossFunction(d, context, expressionNode, isEquals(true), true)
} }

View File

@ -14,6 +14,28 @@ var equalsOperatorScenarios = []expressionScenario{
"D0, P[], (!!bool)::false\n", "D0, P[], (!!bool)::false\n",
}, },
}, },
{
skipDoc: true,
document: "{a: {b: 10}}",
expression: "select(.c != null)",
expected: []string{},
},
{
skipDoc: true,
document: "{a: {b: 10}}",
expression: "select(.d == .c)",
expected: []string{
"D0, P[], (doc)::{a: {b: 10}}\n",
},
},
{
skipDoc: true,
document: "{a: {b: 10}}",
expression: "select(null == .c)",
expected: []string{
"D0, P[], (doc)::{a: {b: 10}}\n",
},
},
{ {
skipDoc: true, skipDoc: true,
document: "{a: { b: {things: \"\"}, f: [1], g: [] }}", document: "{a: { b: {things: \"\"}, f: [1], g: [] }}",

View File

@ -24,7 +24,9 @@ func selectOperator(d *dataTreeNavigator, context Context, expressionNode *Expre
if first != nil { if first != nil {
result := first.Value.(*CandidateNode) result := first.Value.(*CandidateNode)
log.Debugf("result %v", NodeToString(result))
includeResult, errDecoding := isTruthy(result) includeResult, errDecoding := isTruthy(result)
log.Debugf("isTruthy %v", includeResult)
if errDecoding != nil { if errDecoding != nil {
return Context{}, errDecoding return Context{}, errDecoding
} }

View File

@ -24,7 +24,17 @@ 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 resultsForRhs(d *dataTreeNavigator, context Context, lhsCandidate *CandidateNode, rhs Context, calculation crossFunctionCalculation, results *list.List) error { func resultsForRhs(d *dataTreeNavigator, context Context, lhsCandidate *CandidateNode, rhs Context, calculation crossFunctionCalculation, results *list.List, calcWhenEmpty bool) error {
if calcWhenEmpty && rhs.MatchingNodes.Len() == 0 {
resultCandidate, err := calculation(d, context, lhsCandidate, nil)
if err != nil {
return err
}
results.PushBack(resultCandidate)
return nil
}
for rightEl := rhs.MatchingNodes.Front(); rightEl != nil; rightEl = rightEl.Next() { for rightEl := rhs.MatchingNodes.Front(); rightEl != nil; rightEl = rightEl.Next() {
log.Debugf("Applying calc") log.Debugf("Applying calc")
rhsCandidate := rightEl.Value.(*CandidateNode) rhsCandidate := rightEl.Value.(*CandidateNode)
@ -52,14 +62,7 @@ func doCrossFunc(d *dataTreeNavigator, context Context, expressionNode *Expressi
} }
if calcWhenEmpty && lhs.MatchingNodes.Len() == 0 { if calcWhenEmpty && lhs.MatchingNodes.Len() == 0 {
if rhs.MatchingNodes.Len() == 0 { err := resultsForRhs(d, context, nil, rhs, calculation, results, calcWhenEmpty)
resultCandidate, err := calculation(d, context, nil, nil)
if err != nil {
return Context{}, err
}
results.PushBack(resultCandidate)
}
err := resultsForRhs(d, context, nil, rhs, calculation, results)
if err != nil { if err != nil {
return Context{}, err return Context{}, err
} }
@ -68,7 +71,7 @@ func doCrossFunc(d *dataTreeNavigator, context Context, expressionNode *Expressi
for el := lhs.MatchingNodes.Front(); el != nil; el = el.Next() { for el := lhs.MatchingNodes.Front(); el != nil; el = el.Next() {
lhsCandidate := el.Value.(*CandidateNode) lhsCandidate := el.Value.(*CandidateNode)
err := resultsForRhs(d, context, lhsCandidate, rhs, calculation, results) err := resultsForRhs(d, context, lhsCandidate, rhs, calculation, results, calcWhenEmpty)
if err != nil { if err != nil {
return Context{}, err return Context{}, err
} }