Beispiel #1
0
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
}
Beispiel #2
0
// 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
}