diff --git a/topdown/eval.go b/topdown/eval.go index c0f77faaea..432700bd4c 100644 --- a/topdown/eval.go +++ b/topdown/eval.go @@ -567,19 +567,24 @@ func (e *eval) evalNotPartialSupport(negationID uint64, expr *ast.Expr, unknowns } // Save expression that refers to support rule set. - expr = expr.Copy() + + terms := expr.Terms + expr.Terms = nil // Prevent unnecessary copying the terms. + cpy := expr.Copy() + expr.Terms = terms + if len(args) > 0 { terms := make([]*ast.Term, len(args)+1) terms[0] = term for i := 0; i < len(args); i++ { terms[i+1] = args[i] } - expr.Terms = terms + cpy.Terms = terms } else { - expr.Terms = term + cpy.Terms = term } - return e.saveInlinedNegatedExprs([]*ast.Expr{expr}, func() error { + return e.saveInlinedNegatedExprs([]*ast.Expr{cpy}, func() error { return e.next(iter) }) } diff --git a/topdown/input.go b/topdown/input.go index a74ef199f6..b3d542e1af 100644 --- a/topdown/input.go +++ b/topdown/input.go @@ -16,10 +16,7 @@ var errBadPath = fmt.Errorf("bad document path") func mergeTermWithValues(exist *ast.Term, pairs [][2]*ast.Term) (*ast.Term, error) { var result *ast.Term - - if exist != nil { - result = exist.Copy() - } + var init bool for _, pair := range pairs { @@ -31,33 +28,45 @@ func mergeTermWithValues(exist *ast.Term, pairs [][2]*ast.Term) (*ast.Term, erro if len(target) == 1 { result = pair[1] - } else if result == nil { - result = ast.NewTerm(makeTree(target[1:], pair[1])) + init = true } else { - node := result - done := false - for i := 1; i < len(target)-1 && !done; i++ { - if child := node.Get(target[i]); child == nil { + if !init { + result = exist.Copy() + init = true + } + + if result == nil { + result = ast.NewTerm(makeTree(target[1:], pair[1])) + } else { + node := result + done := false + for i := 1; i < len(target)-1 && !done; i++ { + if child := node.Get(target[i]); child == nil { + obj, ok := node.Value.(ast.Object) + if !ok { + return nil, errConflictingDoc + } + obj.Insert(target[i], ast.NewTerm(makeTree(target[i+1:], pair[1]))) + done = true + } else { + node = child + } + } + if !done { obj, ok := node.Value.(ast.Object) if !ok { return nil, errConflictingDoc } - obj.Insert(target[i], ast.NewTerm(makeTree(target[i+1:], pair[1]))) - done = true - } else { - node = child - } - } - if !done { - obj, ok := node.Value.(ast.Object) - if !ok { - return nil, errConflictingDoc + obj.Insert(target[len(target)-1], pair[1]) } - obj.Insert(target[len(target)-1], pair[1]) } } } + if !init { + result = exist + } + return result, nil }