Length compares to null instead of 0 issue #1427

This commit is contained in:
Mike Farah 2022-11-13 11:58:21 +11:00
parent 3e795d020d
commit ffc20f7e2c
6 changed files with 34 additions and 15 deletions

View File

@ -16,7 +16,7 @@ type compareTypePref struct {
func compareOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) { func compareOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
log.Debugf("-- compareOperator") log.Debugf("-- compareOperator")
prefs := expressionNode.Operation.Preferences.(compareTypePref) prefs := expressionNode.Operation.Preferences.(compareTypePref)
return crossFunction(d, context.ReadOnlyClone(), expressionNode, compare(prefs), true) return crossFunction(d, context, expressionNode, compare(prefs), true)
} }
func compare(prefs compareTypePref) func(d *dataTreeNavigator, context Context, lhs *CandidateNode, rhs *CandidateNode) (*CandidateNode, error) { func compare(prefs compareTypePref) func(d *dataTreeNavigator, context Context, lhs *CandidateNode, rhs *CandidateNode) (*CandidateNode, error) {
@ -127,6 +127,10 @@ func compareScalars(context Context, prefs compareTypePref, lhs *yaml.Node, rhs
return lhs.Value > rhs.Value, nil return lhs.Value > rhs.Value, nil
} }
return lhs.Value < rhs.Value, nil return lhs.Value < rhs.Value, nil
} else if lhsTag == "!!null" && rhsTag == "!!null" && prefs.OrEqual {
return true, nil
} else if lhsTag == "!!null" || rhsTag == "!!null" {
return false, nil
} }
return false, fmt.Errorf("%v not yet supported for comparison", lhs.Tag) return false, fmt.Errorf("%v not yet supported for comparison", lhs.Tag)

View File

@ -14,6 +14,13 @@ var compareOperatorScenarios = []expressionScenario{
"D0, P[a], (!!bool)::true\n", "D0, P[a], (!!bool)::true\n",
}, },
}, },
{
skipDoc: true,
expression: "(.k | length) >= 0",
expected: []string{
"D0, P[k], (!!bool)::true\n",
},
},
{ {
skipDoc: true, skipDoc: true,
document: "a: 5\nb: 4", document: "a: 5\nb: 4",
@ -285,28 +292,28 @@ var compareOperatorScenarios = []expressionScenario{
description: "Both sides are null: > is false", description: "Both sides are null: > is false",
expression: ".a > .b", expression: ".a > .b",
expected: []string{ expected: []string{
"D0, P[], (!!bool)::false\n", "D0, P[a], (!!bool)::false\n",
}, },
}, },
{ {
skipDoc: true, skipDoc: true,
expression: ".a < .b", expression: ".a < .b",
expected: []string{ expected: []string{
"D0, P[], (!!bool)::false\n", "D0, P[a], (!!bool)::false\n",
}, },
}, },
{ {
description: "Both sides are null: >= is true", description: "Both sides are null: >= is true",
expression: ".a >= .b", expression: ".a >= .b",
expected: []string{ expected: []string{
"D0, P[], (!!bool)::true\n", "D0, P[a], (!!bool)::true\n",
}, },
}, },
{ {
skipDoc: true, skipDoc: true,
expression: ".a <= .b", expression: ".a <= .b",
expected: []string{ expected: []string{
"D0, P[], (!!bool)::true\n", "D0, P[a], (!!bool)::true\n",
}, },
}, },
@ -350,7 +357,7 @@ var compareOperatorScenarios = []expressionScenario{
document: `a: 5`, document: `a: 5`,
expression: ".b <= .a", expression: ".b <= .a",
expected: []string{ expected: []string{
"D0, P[a], (!!bool)::false\n", "D0, P[b], (!!bool)::false\n",
}, },
}, },
{ {
@ -358,7 +365,7 @@ var compareOperatorScenarios = []expressionScenario{
document: `a: 5`, document: `a: 5`,
expression: ".b < .a", expression: ".b < .a",
expected: []string{ expected: []string{
"D0, P[a], (!!bool)::false\n", "D0, P[b], (!!bool)::false\n",
}, },
}, },
} }

View File

@ -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.ReadOnlyClone(), expressionNode, isEquals(false), true) return crossFunction(d, context, expressionNode, isEquals(false), true)
} }
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) {

View File

@ -9,7 +9,14 @@ var equalsOperatorScenarios = []expressionScenario{
skipDoc: true, skipDoc: true,
expression: ".a == .b", expression: ".a == .b",
expected: []string{ expected: []string{
"D0, P[], (!!bool)::true\n", "D0, P[a], (!!bool)::true\n",
},
},
{
expression: `(.k | length) == 0`,
skipDoc: true,
expected: []string{
"D0, P[k], (!!bool)::true\n",
}, },
}, },
{ {
@ -25,7 +32,7 @@ var equalsOperatorScenarios = []expressionScenario{
document: `a: cat`, document: `a: cat`,
expression: ".b == .a", expression: ".b == .a",
expected: []string{ expected: []string{
"D0, P[a], (!!bool)::false\n", "D0, P[b], (!!bool)::false\n",
}, },
}, },
{ {
@ -50,7 +57,7 @@ var equalsOperatorScenarios = []expressionScenario{
document: "{}", document: "{}",
expression: ".a == .b", expression: ".a == .b",
expected: []string{ expected: []string{
"D0, P[], (!!bool)::true\n", "D0, P[a], (!!bool)::true\n",
}, },
}, },
{ {

View File

@ -76,9 +76,10 @@ var selectOperatorScenarios = []expressionScenario{
}, },
}, },
{ {
skipDoc: true, description: "select does not update the map",
document: `[{animal: cat, legs: {cool: true}}, {animal: fish}]`, skipDoc: true,
expression: `(.[] | select(.legs.cool == true).canWalk) = true | (.[] | .alive.things) = "yes"`, document: `[{animal: cat, legs: {cool: true}}, {animal: fish}]`,
expression: `(.[] | select(.legs.cool == true).canWalk) = true | (.[] | .alive.things) = "yes"`,
expected: []string{ expected: []string{
"D0, P[], (doc)::[{animal: cat, legs: {cool: true}, canWalk: true, alive: {things: yes}}, {animal: fish, alive: {things: yes}}]\n", "D0, P[], (doc)::[{animal: cat, legs: {cool: true}, canWalk: true, alive: {things: yes}}, {animal: fish, alive: {things: yes}}]\n",
}, },

View File

@ -39,7 +39,7 @@ func traverse(context Context, matchingNode *CandidateNode, operation *Operation
log.Debug("Traversing %v", NodeToString(matchingNode)) log.Debug("Traversing %v", NodeToString(matchingNode))
value := matchingNode.Node value := matchingNode.Node
if value.Tag == "!!null" && operation.Value != "[]" { if value.Tag == "!!null" && operation.Value != "[]" && !context.DontAutoCreate {
log.Debugf("Guessing kind") log.Debugf("Guessing kind")
// we must have added this automatically, lets guess what it should be now // we must have added this automatically, lets guess what it should be now
switch operation.Value.(type) { switch operation.Value.(type) {