func Execute(p ExecuteParams, resultChan chan *types.GraphQLResult) {
	var errors []graphqlerrors.GraphQLFormattedError
	var result types.GraphQLResult
	params := BuildExecutionCtxParams{
		Schema:        p.Schema,
		Root:          p.Root,
		AST:           p.AST,
		OperationName: p.OperationName,
		Args:          p.Args,
		Errors:        errors,
		Result:        &result,
		ResultChan:    resultChan,
	}
	exeContext := buildExecutionContext(params)
	if result.HasErrors() {
		return
	}
	defer func() {
		if r := recover(); r != nil {
			var err error
			if r, ok := r.(error); ok {
				err = graphqlerrors.FormatError(r)
			}
			exeContext.Errors = append(exeContext.Errors, graphqlerrors.FormatError(err))
			result.Errors = exeContext.Errors
			resultChan <- &result
		}
	}()
	eOperationParams := ExecuteOperationParams{
		ExecutionContext: exeContext,
		Root:             p.Root,
		Operation:        exeContext.Operation,
	}
	executeOperation(eOperationParams, resultChan)
}
Exemple #2
0
func buildExecutionContext(p BuildExecutionCtxParams) (eCtx ExecutionContext) {
	operations := make(map[string]ast.Definition)
	fragments := make(map[string]ast.Definition)
	for _, statement := range p.AST.Definitions {
		switch stm := statement.(type) {
		case *ast.OperationDefinition:
			log.Println("kinds.OperationDefinition")
			key := ""
			if stm.GetName().Value != "" {
				key = stm.GetName().Value
			}
			operations[key] = stm
			break
		case *ast.FragmentDefinition:
			log.Println("kinds.FragmentDefinition")
			fragments[stm.GetName().Value] = stm
			break
		default:
			log.Println("default")
		}
	}
	log.Printf("debug - operations: %v", operations)
	if (p.OperationName == "") && (len(operations) != 1) {
		err := graphqlerrors.NewGraphQLFormattedError("Must provide operation name if query contains multiple operations")
		p.Result.Errors = append(p.Result.Errors, err)
		p.ResultChan <- p.Result
		return eCtx
	}
	var opName string
	if p.OperationName == "" {
		for k, _ := range operations {
			opName = k
			break
		}
	}
	operation, found := operations[opName]
	if !found {
		var result types.GraphQLResult
		err := graphqlerrors.NewGraphQLFormattedError(fmt.Sprintf("Unknown operation name: %s", opName))
		result.Errors = append(result.Errors, err)
		return eCtx
	}
	variables := GetVariableValues(p.Schema, operation.GetVariableDefinitions(), p.Args)
	eCtx.Schema = p.Schema
	eCtx.Fragments = fragments
	eCtx.Root = p.Root
	eCtx.Operation = operation
	eCtx.Variables = variables
	eCtx.Errors = p.Errors
	return eCtx
}
Exemple #3
0
// Implements the "Evaluating selection sets" section of the spec for "write" mode.
func executeFieldsSerially(p ExecuteFieldsParams, resultChan chan *types.GraphQLResult) {
	if p.Source == nil {
		p.Source = map[string]interface{}{}
	}
	if p.Fields == nil {
		p.Fields = map[string][]*ast.Field{}
	}
	var result types.GraphQLResult

	finalResults := map[string]interface{}{}
	for responseName, fieldASTs := range p.Fields {
		resolved, state := resolveField(p.ExecutionContext, p.ParentType, p.Source, fieldASTs)
		if state.hasNoFieldDefs {
			continue
		}
		finalResults[responseName] = resolved
	}
	result.Errors = p.ExecutionContext.Errors
	result.Data = finalResults
	resultChan <- &result
}
Exemple #4
0
// Extracts the root type of the operation from the schema.
func getOperationRootType(schema types.GraphQLSchema, operation ast.Definition, r chan *types.GraphQLResult) (objType *types.GraphQLObjectType) {
	if operation == nil {
		var result types.GraphQLResult
		err := graphqlerrors.NewGraphQLFormattedError("Can only execute queries and mutations")
		result.Errors = append(result.Errors, err)
		r <- &result
		return objType
	}
	switch operation.GetOperation() {
	case "query":
		return schema.GetQueryType()
	case "mutation":
		mutationType := schema.GetMutationType()
		if mutationType.Name == "" {
			var result types.GraphQLResult
			err := graphqlerrors.NewGraphQLFormattedError("Schema is not configured for mutations")
			result.Errors = append(result.Errors, err)
			r <- &result
			return objType
		}
		return mutationType
	default:
		var result types.GraphQLResult
		err := graphqlerrors.NewGraphQLFormattedError("Can only execute queries and mutations")
		result.Errors = append(result.Errors, err)
		r <- &result
		return objType
	}
}
Exemple #5
0
func Execute(p ExecuteParams, resultChan chan *types.GraphQLResult) {
	var errors []error
	var result types.GraphQLResult
	params := BuildExecutionCtxParams{
		Schema:        p.Schema,
		Root:          p.Root,
		AST:           p.AST,
		OperationName: p.OperationName,
		Args:          p.Args,
		Errors:        errors,
		Result:        &result,
		ResultChan:    resultChan,
	}
	exeContext := buildExecutionContext(params)
	if result.HasErrors() {
		return
	}
	eOperationParams := ExecuteOperationParams{
		ExecutionContext: exeContext,
		Root:             p.Root,
		Operation:        exeContext.Operation,
	}
	executeOperation(eOperationParams, resultChan)
}
Exemple #6
0
func executeOperation(p ExecuteOperationParams, resultChan chan *types.GraphQLResult) {
	var results types.GraphQLResult
	operationType := getOperationRootType(p.ExecutionContext.Schema, p.Operation, resultChan)

	collectFieldsParams := CollectFieldsParams{
		ExeContext:    p.ExecutionContext,
		OperationType: operationType,
		SelectionSet:  p.Operation.GetSelectionSet(),
	}
	fields := collectFields(collectFieldsParams)
	executeFieldsParams := ExecuteFieldsParams{
		ExecutionContext: p.ExecutionContext,
		ParentType:       operationType,
		Source:           p.Root,
		Fields:           fields,
	}
	if p.Operation.GetOperation() == "mutation" {
		executeFieldsSerially(executeFieldsParams, resultChan)
		return
	}
	results = executeFields(executeFieldsParams)
	results.Errors = p.ExecutionContext.Errors
	resultChan <- &results
}