Fixed union infinite loop #930

This commit is contained in:
Mike Farah 2021-09-05 11:07:40 +10:00
parent 8941573c1a
commit 3543a2dbdc
4 changed files with 48 additions and 18 deletions

View File

@ -2,8 +2,10 @@ package yqlib
import (
"container/list"
"fmt"
"github.com/jinzhu/copier"
logging "gopkg.in/op/go-logging.v1"
)
type Context struct {
@ -51,6 +53,14 @@ func (n *Context) ChildContext(results *list.List) Context {
return clone
}
func (n *Context) ToString() string {
if !log.IsEnabledFor(logging.DEBUG) {
return ""
}
result := fmt.Sprintf("Context\nDontAutoCreate: %v\n", n.DontAutoCreate)
return result + NodesToString(n.MatchingNodes)
}
func (n *Context) Clone() Context {
clone := Context{}
err := copier.Copy(&clone, n)

View File

@ -179,7 +179,7 @@ func NodesToString(collection *list.List) string {
return ""
}
result := ""
result := fmt.Sprintf("%v results\n", collection.Len())
for el := collection.Front(); el != nil; el = el.Next() {
result = result + "\n" + NodeToString(el.Value.(*CandidateNode))
}

View File

@ -1,17 +1,36 @@
package yqlib
func unionOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
log.Debug("unionOperator")
log.Debug("context: %v", NodesToString(context.MatchingNodes))
lhs, err := d.GetMatchingNodes(context, expressionNode.Lhs)
if err != nil {
return Context{}, err
}
log.Debug("lhs: %v", NodesToString(lhs.MatchingNodes))
log.Debug("rhs input: %v", NodesToString(context.MatchingNodes))
log.Debug("rhs: %v", expressionNode.Rhs.Operation.toString())
rhs, err := d.GetMatchingNodes(context, expressionNode.Rhs)
if err != nil {
return Context{}, err
}
for el := rhs.MatchingNodes.Front(); el != nil; el = el.Next() {
node := el.Value.(*CandidateNode)
lhs.MatchingNodes.PushBack(node)
log.Debug("lhs: %v", lhs.ToString())
log.Debug("rhs: %v", rhs.ToString())
// this can happen when both expressions modify the context
// instead of creating their own.
/// (.foo = "bar"), (.thing = "cat")
if rhs.MatchingNodes != lhs.MatchingNodes {
for el := rhs.MatchingNodes.Front(); el != nil; el = el.Next() {
node := el.Value.(*CandidateNode)
log.Debug("processing %v", NodeToString(node))
lhs.MatchingNodes.PushBack(node)
}
}
log.Debug("all together: %v", lhs.ToString())
return lhs, nil
}

View File

@ -5,20 +5,21 @@ import (
)
var unionOperatorScenarios = []expressionScenario{
// {
// skipDoc: true,
// document: "{}",
// expression: `(.a, .b.c) as $x`,
// expected: []string{
// "D0, P[], (doc)::{}\n",
// },
// },
// {
// skipDoc: true,
// document: "{}",
// expression: `(.a, .b.c)`,
// expected: []string{},
// },
{
skipDoc: true,
document: "{}",
expression: `(.a, .b.c) as $x`,
expected: []string{
"D0, P[], (doc)::{}\n",
},
},
{
skipDoc: true,
expression: `(.foo = "bar"), (.toe = "jam")`,
expected: []string{
"D0, P[], ()::foo: bar\ntoe: jam\n",
},
},
{
description: "Combine scalars",
expression: `1, true, "cat"`,