Fixed variable operator to work like jq

This commit is contained in:
Mike Farah 2023-02-28 16:14:42 +11:00
parent 0cd15867d0
commit eb9181670e
9 changed files with 44 additions and 16 deletions

View File

@ -329,7 +329,16 @@ idPath=".a" originalPath=".myArray" otherPath=".newArray" yq eval-all '
``` ```
will output will output
```yaml ```yaml
myArray: [] myArray:
- a: apple
b: appleB2
- a: kiwi
b: kiwiB
- a: banana
b: bananaB
c: bananaC
- a: dingo
c: dingoC
something: else something: else
``` ```

View File

@ -16,7 +16,7 @@ var alternativeOperatorScenarios = []expressionScenario{
}, },
{ {
skipDoc: true, skipDoc: true,
expression: `(.b // "hello") as $x`, expression: `(.b // "hello") as $x | .`,
document: `a: bridge`, document: `a: bridge`,
expected: []string{ expected: []string{
"D0, P[], (doc)::a: bridge\n", "D0, P[], (doc)::a: bridge\n",

View File

@ -102,7 +102,7 @@ var booleanOperatorScenarios = []expressionScenario{
{ {
skipDoc: true, skipDoc: true,
document: `[{pet: cat}]`, document: `[{pet: cat}]`,
expression: `any_c(.name == "harry") as $c`, expression: `any_c(.name == "harry") as $c | .`,
expected: []string{ expected: []string{
"D0, P[], (doc)::[{pet: cat}]\n", "D0, P[], (doc)::[{pet: cat}]\n",
}, },
@ -110,9 +110,17 @@ var booleanOperatorScenarios = []expressionScenario{
{ {
skipDoc: true, skipDoc: true,
document: `[{pet: cat}]`, document: `[{pet: cat}]`,
expression: `all_c(.name == "harry") as $c`, expression: `any_c(.name == "harry") as $c | $c`,
expected: []string{ expected: []string{
"D0, P[], (doc)::[{pet: cat}]\n", "D0, P[], (!!bool)::false\n",
},
},
{
skipDoc: true,
document: `[{pet: cat}]`,
expression: `all_c(.name == "harry") as $c | $c`,
expected: []string{
"D0, P[], (!!bool)::false\n",
}, },
}, },
{ {
@ -185,7 +193,7 @@ var booleanOperatorScenarios = []expressionScenario{
{ {
skipDoc: true, skipDoc: true,
document: `{}`, document: `{}`,
expression: `(.a.b or .c) as $x`, expression: `(.a.b or .c) as $x | .`,
expected: []string{ expected: []string{
"D0, P[], (doc)::{}\n", "D0, P[], (doc)::{}\n",
}, },
@ -193,7 +201,7 @@ var booleanOperatorScenarios = []expressionScenario{
{ {
skipDoc: true, skipDoc: true,
document: `{}`, document: `{}`,
expression: `(.a.b and .c) as $x`, expression: `(.a.b and .c) as $x | .`,
expected: []string{ expected: []string{
"D0, P[], (doc)::{}\n", "D0, P[], (doc)::{}\n",
}, },

View File

@ -47,7 +47,7 @@ var equalsOperatorScenarios = []expressionScenario{
{ {
skipDoc: true, skipDoc: true,
document: "{}", document: "{}",
expression: "(.a == .b) as $x", expression: "(.a == .b) as $x | .",
expected: []string{ expected: []string{
"D0, P[], (doc)::{}\n", "D0, P[], (doc)::{}\n",
}, },
@ -63,7 +63,7 @@ var equalsOperatorScenarios = []expressionScenario{
{ {
skipDoc: true, skipDoc: true,
document: "{}", document: "{}",
expression: "(.a != .b) as $x", expression: "(.a != .b) as $x | .",
expected: []string{ expected: []string{
"D0, P[], (doc)::{}\n", "D0, P[], (doc)::{}\n",
}, },

View File

@ -16,7 +16,7 @@ var hasOperatorScenarios = []expressionScenario{
{ {
skipDoc: true, skipDoc: true,
document: `a: hello`, document: `a: hello`,
expression: `has(.b) as $c`, expression: `has(.b) as $c | .`,
expected: []string{ expected: []string{
"D0, P[], (doc)::a: hello\n", "D0, P[], (doc)::a: hello\n",
}, },

View File

@ -8,7 +8,7 @@ var subtractOperatorScenarios = []expressionScenario{
{ {
skipDoc: true, skipDoc: true,
document: `{}`, document: `{}`,
expression: "(.a - .b) as $x", expression: "(.a - .b) as $x | .",
expected: []string{ expected: []string{
"D0, P[], (doc)::{}\n", "D0, P[], (doc)::{}\n",
}, },

View File

@ -151,7 +151,7 @@ var traversePathOperatorScenarios = []expressionScenario{
{ {
skipDoc: true, skipDoc: true,
document: `c: dog`, document: `c: dog`,
expression: `.[.a.b] as $x`, expression: `.[.a.b] as $x | .`,
expected: []string{ expected: []string{
"D0, P[], (doc)::c: dog\n", "D0, P[], (doc)::c: dog\n",
}, },

View File

@ -8,7 +8,7 @@ var unionOperatorScenarios = []expressionScenario{
{ {
skipDoc: true, skipDoc: true,
document: "{}", document: "{}",
expression: `(.a, .b.c) as $x`, expression: `(.a, .b.c) as $x | .`,
expected: []string{ expected: []string{
"D0, P[], (doc)::{}\n", "D0, P[], (doc)::{}\n",
}, },

View File

@ -28,6 +28,17 @@ func useWithPipe(d *dataTreeNavigator, context Context, originalExp *ExpressionN
func variableLoop(d *dataTreeNavigator, context Context, originalExp *ExpressionNode) (Context, error) { func variableLoop(d *dataTreeNavigator, context Context, originalExp *ExpressionNode) (Context, error) {
log.Debug("variable loop!") log.Debug("variable loop!")
results := list.New() results := list.New()
var evaluateAllTogether = true
for matchEl := context.MatchingNodes.Front(); matchEl != nil; matchEl = matchEl.Next() {
evaluateAllTogether = evaluateAllTogether && matchEl.Value.(*CandidateNode).EvaluateTogether
if !evaluateAllTogether {
break
}
}
if evaluateAllTogether {
return variableLoopSingleChild(d, context, originalExp)
}
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() { for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
result, err := variableLoopSingleChild(d, context.SingleChildContext(el.Value.(*CandidateNode)), originalExp) result, err := variableLoopSingleChild(d, context.SingleChildContext(el.Value.(*CandidateNode)), originalExp)
if err != nil { if err != nil {
@ -56,17 +67,17 @@ func variableLoopSingleChild(d *dataTreeNavigator, context Context, originalExp
// now we loop over lhs, set variable to each result and calculate originalExp.Rhs // now we loop over lhs, set variable to each result and calculate originalExp.Rhs
for el := lhs.MatchingNodes.Front(); el != nil; el = el.Next() { for el := lhs.MatchingNodes.Front(); el != nil; el = el.Next() {
log.Debug("PROCESSING VARIABLE: ", NodeToString(el.Value.(*CandidateNode)))
var variableValue = list.New() var variableValue = list.New()
if prefs.IsReference { if prefs.IsReference {
variableValue.PushBack(el.Value) variableValue.PushBack(el.Value)
} else { } else {
copy, err := el.Value.(*CandidateNode).Copy() candidateCopy, err := el.Value.(*CandidateNode).Copy()
if err != nil { if err != nil {
return Context{}, err return Context{}, err
} }
variableValue.PushBack(copy) variableValue.PushBack(candidateCopy)
} }
log.Debug("PROCESSING VARIABLE: ", NodeToString(el.Value.(*CandidateNode)))
newContext := context.ChildContext(context.MatchingNodes) newContext := context.ChildContext(context.MatchingNodes)
newContext.SetVariable(variableName, variableValue) newContext.SetVariable(variableName, variableValue)