Exemplo n.º 1
0
        /// Given a syntax of someField { fields, to, selection, from, object }
        /// it will build the correct select statement
        private IGraphQLNode BuildDynamicSelectForObjectGraph(string query, string name, EntityGraphQLParser.EntityQueryContext context, QueryResult rootField)
        {
            var selectWasNull = false;

            if (selectContext == null)
            {
                selectContext = Expression.Parameter(schemaProvider.ContextType);
                selectWasNull = true;
            }

            if (schemaProvider.TypeHasField(selectContext.Type.Name, name, new string[0]))
            {
                name = schemaProvider.GetActualFieldName(selectContext.Type.Name, name);
            }

            try
            {
                Expression exp = rootField.LambdaExpression.Body;

                var oldContext     = selectContext;
                var rootFieldParam = Expression.Parameter(exp.Type);
                selectContext = rootField.IsMutation ? rootFieldParam : exp;
                // visit child fields. Will be field or entityQueries again
                var fieldExpressions = context.fields.children.Select(c => Visit(c)).Where(n => n != null).ToList();

                var newExp   = ExpressionUtil.CreateNewExpression(selectContext, fieldExpressions, schemaProvider);
                var anonType = newExp.Type;
                // make a null check from this new expression
                if (!rootField.IsMutation)
                {
                    newExp = Expression.Condition(Expression.MakeBinary(ExpressionType.Equal, selectContext, Expression.Constant(null)), Expression.Constant(null, anonType), newExp, anonType);
                }
                selectContext = oldContext;

                var t          = MergeConstantParametersFromFields(rootField, fieldExpressions, rootFieldParam);
                var parameters = t.Item1;
                var constantParameterValues = t.Item2;

                var graphQLNode = new GraphQLNode(name, new QueryResult((ExpressionResult)newExp, parameters, constantParameterValues), (ExpressionResult)exp);
                if (selectWasNull)
                {
                    selectContext = null;
                }
                return(graphQLNode);
            }
            catch (EntityGraphQLCompilerException ex)
            {
                throw SchemaException.MakeFieldCompileError(query, ex.Message);
            }
        }
Exemplo n.º 2
0
 public IGraphQLBaseNode ParseFieldSelect(ExpressionResult expContext, string name, EntityGraphQLParser.ObjectSelectionContext context)
 {
     try
     {
         IGraphQLBaseNode graphQLNode = null;
         if (expContext.Type.IsEnumerableOrArray())
         {
             //var listExp = Compiler.Util.ExpressionUtil.FindDistinct(result.ExpressionResult);
             //if (listExp.Item1 != null)
             //{
             //    var item1 = (ExpressionResult)listExp.Item1;
             //    item1.AddConstantParameters(result.ExpressionResult.ConstantParameters);
             //    graphQLNode = BuildDynamicSelectOnCollection(new CompiledQueryResult(item1, result.ContextParams), name, context);
             //    graphQLNode.SetNodeExpression((ExpressionResult)Compiler.Util.ExpressionUtil.CombineExpressions(graphQLNode.GetNodeExpression(), listExp.Item2));
             //}
             //else
             //{
             //    graphQLNode = BuildDynamicSelectOnCollection(result, name, context);
             //}
             graphQLNode = BuildDynamicSelectOnCollection(expContext, name, context);
         }
         else
         {
             // Could be a list.First() that we need to turn into a select, or
             // other levels are object selection. e.g. from the top level people query I am selecting all their children { field1, etc. }
             // Can we turn a list.First() into and list.Select().First()
             var listExp = ExpressionUtil.FindIEnumerable(expContext);
             if (listExp.Item1 != null)
             {
                 // yes we can
                 // rebuild the ExpressionResult so we keep any ConstantParameters
                 var item1 = (ExpressionResult)listExp.Item1;
                 item1.AddConstantParameters(expContext.ConstantParameters);
                 item1.AddServices(expContext.Services);
                 graphQLNode = BuildDynamicSelectOnCollection(item1, name, context);
                 graphQLNode.SetCombineExpression(listExp.Item2);
             }
             else
             {
                 graphQLNode = BuildDynamicSelectForObjectGraph(expContext, currentExpressionContext.AsParameter(), name, context);
             }
         }
         return(graphQLNode);
     }
     catch (EntityGraphQLCompilerException ex)
     {
         throw SchemaException.MakeFieldCompileError($"Error compiling field {name}", ex.Message);
     }
 }
Exemplo n.º 3
0
        /// Given a syntax of someField { fields, to, selection, from, object }
        /// it will build the correct select statement
        private IGraphQLNode BuildDynamicSelectForObjectGraph(string query, string name, EntityGraphQLParser.EntityQueryContext context, CompiledQueryResult rootField)
        {
            var selectWasNull = false;

            if (selectContext == null)
            {
                selectContext = Expression.Parameter(schemaProvider.ContextType);
                selectWasNull = true;
            }

            if (schemaProvider.TypeHasField(selectContext.Type.Name, name, new string[0]))
            {
                name = schemaProvider.GetActualFieldName(selectContext.Type.Name, name);
            }

            try
            {
                var exp = (Expression)rootField.ExpressionResult;

                var oldContext     = selectContext;
                var rootFieldParam = Expression.Parameter(exp.Type);
                selectContext = rootField.IsMutation ? rootFieldParam : exp;
                // visit child fields. Will be field or entityQueries again
                var fieldExpressions = context.fields.children.Select(c => Visit(c)).Where(n => n != null).ToList();

                var graphQLNode = new GraphQLNode(schemaProvider, fragments, name, null, (ExpressionResult)selectContext, (rootField.IsMutation ? new ParameterExpression[] { rootFieldParam } : rootField.ContextParams.ToArray()), fieldExpressions, null);
                if (rootField != null && rootField.ConstantParameters != null)
                {
                    graphQLNode.AddConstantParameters(rootField.ConstantParameters);
                }

                selectContext = oldContext;

                if (selectWasNull)
                {
                    selectContext = null;
                }
                return(graphQLNode);
            }
            catch (EntityGraphQLCompilerException ex)
            {
                throw SchemaException.MakeFieldCompileError(query, ex.Message);
            }
        }
Exemplo n.º 4
0
        /// <summary>
        /// Given a syntax of { fields, to, selection, from, object } with a context
        /// it will build the correct select statement
        /// </summary>
        /// <param name="name"></param>
        /// <param name="context"></param>
        /// <param name="selectContext"></param>
        /// <returns></returns>
        private IGraphQLBaseNode BuildDynamicSelectForObjectGraph(ExpressionResult selectFromExp, ParameterExpression selectFromParam, string name, EntityGraphQLParser.ObjectSelectionContext context)
        {
            try
            {
                // visit child fields. Will be field or entityQueries again
                // These expression will be built on the element type
                var oldContext = currentExpressionContext;
                currentExpressionContext = selectFromExp;
                var fieldExpressions = context.children.Select(c => Visit(c)).Where(n => n != null).ToList();
                currentExpressionContext = oldContext;

                var graphQLNode = new GraphQLQueryNode(schemaProvider, fragments, name, selectFromExp, selectFromParam, fieldExpressions, selectFromExp);
                return(graphQLNode);
            }
            catch (EntityGraphQLCompilerException ex)
            {
                throw SchemaException.MakeFieldCompileError($"Failed compiling field {name}", ex.Message);
            }
        }
Exemplo n.º 5
0
        /// <summary>
        /// Given a syntax of { fields, to, selection, from, object } with a context
        /// it will build the correct select statement
        /// </summary>
        /// <param name="name"></param>
        /// <param name="context"></param>
        /// <param name="selectContext"></param>
        /// <returns></returns>
        private IGraphQLBaseNode BuildDynamicSelectForObjectGraph(ExpressionResult selectFromExp, ParameterExpression selectFromParam, string name, EntityGraphQLParser.ObjectSelectionContext context)
        {
            try
            {
                // visit child fields. Will be field or entityQueries again
                // These expression will be built on the element type
                var oldContext = currentExpressionContext;
                currentExpressionContext = selectFromExp;
                ParameterExpression replacementParameter = null;
                // we might be using a service i.e. ctx => WithService((T r) => r.DoSomething(ctx.Entities.Select(f => f.Id).ToList()))
                // if we can we want to avoid calling that multiple times with a expression like
                // r.DoSomething(ctx.Entities.Select(f => f.Id).ToList()) == null ? null : new {
                //      Field = r.DoSomething(ctx.Entities.Select(f => f.Id).ToList()).Blah
                // }
                // by wrapping the whole thing in a method that does the null check once.
                // This means we build the fieldExpressions on a parameter of the result type
                // We can only do that if it doesn't use the oldContext unless the oldContext is the root context
                // i.e we can't do this on a field on a type because we don't have that value as it might be a selection from an ORM
                bool wrapField = (oldContext.Type == schemaProvider.ContextType || oldContext.NodeType == ExpressionType.Parameter) && currentExpressionContext.Services.Any();
                if (wrapField)
                {
                    // replace with a parameter. The expression is compiled at execution time once
                    replacementParameter     = Expression.Parameter(selectFromExp.Type, "null_wrap");
                    currentExpressionContext = (ExpressionResult)replacementParameter;
                }
                var fieldExpressions = context.children.Select(c => Visit(c)).Where(n => n != null).ToList();
                currentExpressionContext = oldContext;

                var graphQLNode = new GraphQLQueryNode(schemaProvider, fragments, name, selectFromExp, selectFromParam, fieldExpressions, selectFromExp)
                {
                    IsWrapped = wrapField
                };
                return(graphQLNode);
            }
            catch (EntityGraphQLCompilerException ex)
            {
                throw SchemaException.MakeFieldCompileError($"Failed compiling field {name}", ex.Message);
            }
        }
Exemplo n.º 6
0
        /// <summary>
        /// We compile each entityQuery with EqlCompiler and build a Select call from the fields
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        public override IGraphQLBaseNode VisitEntityQuery(EntityGraphQLParser.EntityQueryContext context)
        {
            string name;
            string query;

            if (context.alias != null)
            {
                name  = context.alias.name.GetText();
                query = context.entity.GetText();
            }
            else
            {
                query = context.entity.GetText();
                name  = query;
                if (name.IndexOf(".") > -1)
                {
                    name = name.Substring(0, name.IndexOf("."));
                }
                if (name.IndexOf("(") > -1)
                {
                    name = name.Substring(0, name.IndexOf("("));
                }
            }

            try
            {
                CompiledQueryResult result = null;
                if (selectContext == null)
                {
                    // top level are queries on the context
                    result = EqlCompiler.Compile(query, schemaProvider, methodProvider, variables);
                }
                else
                {
                    result = EqlCompiler.CompileWith(query, selectContext, schemaProvider, methodProvider, variables);
                }
                var exp = result.ExpressionResult;

                IGraphQLNode graphQLNode = null;
                if (exp.Type.IsEnumerableOrArray())
                {
                    graphQLNode = BuildDynamicSelectOnCollection(result, name, context);
                }
                else
                {
                    // Could be a list.First() that we need to turn into a select, or
                    // other levels are object selection. e.g. from the top level people query I am selecting all their children { field1, etc. }
                    // Can we turn a list.First() into and list.Select().First()
                    var listExp = Compiler.Util.ExpressionUtil.FindIEnumerable(result.ExpressionResult);
                    if (listExp.Item1 != null)
                    {
                        // yes we can
                        // rebuild the ExpressionResult so we keep any ConstantParameters
                        var item1 = (ExpressionResult)listExp.Item1;
                        item1.AddConstantParameters(result.ExpressionResult.ConstantParameters);
                        graphQLNode = BuildDynamicSelectOnCollection(new CompiledQueryResult(item1, result.ContextParams), name, context);
                        graphQLNode.SetNodeExpression((ExpressionResult)Compiler.Util.ExpressionUtil.CombineExpressions(graphQLNode.GetNodeExpression(), listExp.Item2));
                    }
                    else
                    {
                        graphQLNode = BuildDynamicSelectForObjectGraph(query, name, context, result);
                    }
                }
                // the query result may be a mutation
                if (result.IsMutation)
                {
                    return(new GraphQLMutationNode(result, graphQLNode));
                }
                return(graphQLNode);
            }
            catch (EntityGraphQLCompilerException ex)
            {
                throw SchemaException.MakeFieldCompileError(query, ex.Message);
            }
        }