func mangleEvent(ctx context.Context, store *storage.Storage, txn storage.Transaction, event *topdown.Event) error { // Replace bindings with ref values with the values from storage. cpy := event.Locals.Copy() var err error event.Locals.Iter(func(k, v ast.Value) bool { if r, ok := v.(ast.Ref); ok { var path storage.Path path, err = storage.NewPathForRef(r) if err != nil { return true } var doc interface{} doc, err = store.Read(ctx, txn, path) if err != nil { return true } v, err = ast.InterfaceToValue(doc) if err != nil { return true } cpy.Put(k, v) } return false }) event.Locals = cpy switch node := event.Node.(type) { case *ast.Rule: event.Node = topdown.PlugHead(node.Head(), event.Locals.Get) case *ast.Expr: event.Node = topdown.PlugExpr(node, event.Locals.Get) } return nil }
// checkAndSetAllPaths returns true if all search paths should be included for // this query. All search paths are included for negated expressions, full // references to partial definitions of objects and sets, and comprehensions. func (t *truth) checkAndSetAllPaths(event *topdown.Event) bool { _, ok := t.allPaths[event.QueryID] if ok { return ok } _, ok = t.allPaths[event.ParentID] if ok { t.allPaths[event.QueryID] = struct{}{} return ok } if event.Op != topdown.EnterOp { return false } prevQuery := t.byQuery[event.ParentID] prev := prevQuery[len(prevQuery)-1] prevExpr := prev.event.Node.(*ast.Expr) switch node := event.Node.(type) { case *ast.Rule: if node.DocKind() == ast.PartialObjectDoc || node.DocKind() == ast.PartialSetDoc { plugged := topdown.PlugExpr(prevExpr, prev.event.Locals.Get) found := false ast.WalkRefs(plugged, func(r ast.Ref) bool { rules := t.compiler.GetRulesWithPrefix(r) for _, rule := range rules { if rule.Equal(node) { found = true return true } } return false }) if found { t.allPaths[event.QueryID] = struct{}{} return true } } case ast.Body: if prevExpr.Negated { t.allPaths[event.QueryID] = struct{}{} } else { found := false ast.WalkClosures(prevExpr, func(x interface{}) bool { if ac, ok := x.(*ast.ArrayComprehension); ok { if ac.Body.Equal(node) { found = true return true } } return false }) if found { t.allPaths[event.QueryID] = struct{}{} return true } } } return false }