Esempio n. 1
0
func (s *Server) execQuery(ctx context.Context, compiler *ast.Compiler, txn storage.Transaction, query ast.Body, explainMode explainModeV1) (interface{}, error) {

	t := topdown.New(ctx, query, s.Compiler(), s.store, txn)

	var buf *topdown.BufferTracer

	if explainMode != explainOffV1 {
		buf = topdown.NewBufferTracer()
		t.Tracer = buf
	}

	resultSet := adhocQueryResultSetV1{}

	err := topdown.Eval(t, func(t *topdown.Topdown) error {
		result := map[string]interface{}{}
		var err error
		t.Locals.Iter(func(k, v ast.Value) bool {
			kv, ok := k.(ast.Var)
			if !ok {
				return false
			}
			if kv.IsWildcard() {
				return false
			}
			vv, e := topdown.ValueToInterface(v, t)
			if e != nil {
				err = e
				return true
			}
			result[string(kv)] = vv
			return false
		})
		if err != nil {
			return err
		}
		if len(result) > 0 {
			resultSet = append(resultSet, result)
		}
		return nil
	})

	if err != nil {
		return nil, err
	}

	switch explainMode {
	case explainFullV1:
		return newTraceV1(*buf), nil
	case explainTruthV1:
		answer, err := explain.Truth(compiler, *buf)
		if err != nil {
			return nil, err
		}
		return newTraceV1(answer), nil
	default:
		return resultSet, nil
	}
}
Esempio n. 2
0
File: repl.go Progetto: tsandall/opa
func (r *REPL) printTrace(ctx context.Context, compiler *ast.Compiler, trace []*topdown.Event) {
	if r.explain == explainTruth {
		answer, err := explain.Truth(compiler, trace)
		if err != nil {
			fmt.Fprintf(r.output, "error: %v\n", err)
		}
		trace = answer
	}
	mangleTrace(ctx, r.store, r.txn, trace)
	topdown.PrettyTrace(r.output, trace)
}
Esempio n. 3
0
func (s *Server) v1DataGet(w http.ResponseWriter, r *http.Request) {

	// Gather request parameters.
	ctx := r.Context()
	vars := mux.Vars(r)
	path := stringPathToDataRef(vars["path"])
	pretty := getPretty(r.URL.Query()["pretty"])
	explainMode := getExplain(r.URL.Query()["explain"])
	request, nonGround, err := parseRequest(r.URL.Query()[ParamRequestV1])

	if err != nil {
		handleError(w, 400, err)
		return
	}

	if nonGround && explainMode != explainOffV1 {
		handleError(w, 400, fmt.Errorf("explanations with non-ground request values not supported"))
		return
	}

	// Prepare for query.
	txn, err := s.store.NewTransaction(ctx)
	if err != nil {
		handleErrorAuto(w, err)
		return
	}

	defer s.store.Close(ctx, txn)

	compiler := s.Compiler()
	params := topdown.NewQueryParams(ctx, compiler, s.store, txn, request, path)

	var buf *topdown.BufferTracer
	if explainMode != explainOffV1 {
		buf = topdown.NewBufferTracer()
		params.Tracer = buf
	}

	// Execute query.
	qrs, err := topdown.Query(params)

	// Handle results.
	if err != nil {
		handleErrorAuto(w, err)
		return
	}

	if qrs.Undefined() {
		if explainMode == explainFullV1 {
			handleResponseJSON(w, 404, newTraceV1(*buf), pretty)
		} else {
			handleResponse(w, 404, nil)
		}
		return
	}

	if nonGround {
		handleResponseJSON(w, 200, newQueryResultSetV1(qrs), pretty)
		return
	}

	result := qrs[0].Result

	switch explainMode {
	case explainOffV1:
		handleResponseJSON(w, 200, result, pretty)
	case explainFullV1:
		handleResponseJSON(w, 200, newTraceV1(*buf), pretty)
	case explainTruthV1:
		answer, err := explain.Truth(compiler, *buf)
		if err != nil {
			handleErrorAuto(w, err)
			return
		}
		handleResponseJSON(w, 200, newTraceV1(answer), pretty)
	}
}