Example #1
0
        public override void VisitMainFromClause(
            [NotNull] MainFromClause fromClause, [NotNull] QueryModel queryModel)
        {
            Check.NotNull(fromClause, nameof(fromClause));
            Check.NotNull(queryModel, nameof(queryModel));

            _expression = CompileMainFromClauseExpression(fromClause, queryModel);

            var sequenceType = _expression.Type.GetSequenceType();

            var elementScoped
                = sequenceType.IsConstructedGenericType &&
                  sequenceType.GetGenericTypeDefinition() == typeof(QueryResultScope <>);

            Type elementType;

            if (elementScoped)
            {
                elementType = sequenceType.GetTypeInfo().GenericTypeArguments[0];
            }
            else
            {
                elementType = sequenceType;
                _expression = CreateScope(_expression, elementType, fromClause);
            }

            _expression
                = Expression.Call(
                      LinqOperatorProvider.SelectMany
                      .MakeGenericMethod(typeof(QueryResultScope), typeof(QueryResultScope)),
                      Expression.Call(
                          LinqOperatorProvider.ToSequence
                          .MakeGenericMethod(typeof(QueryResultScope)),
                          QueryResultScopeParameter),
                      Expression.Lambda(_expression, QueryResultScopeParameter));

            if (!_queryCompilationContext.QuerySourceMapping.ContainsMapping(fromClause))
            {
                _queryCompilationContext.QuerySourceMapping.AddMapping(
                    fromClause,
                    QueryResultScope.GetResult(QueryResultScopeParameter, fromClause, elementType));
            }
        }
Example #2
0
 public virtual object GetResult([NotNull] IQuerySource querySource)
 => _querySource == querySource
         ? UntypedResult
         : _parentScope.GetResult(querySource);
Example #3
0
        private Expression LiftSubQuery(
            IQuerySource querySource, Expression itemsExpression, QueryModel queryModel, Expression expression)
        {
            SelectExpression subSelectExpression;

            if (_subqueriesBySource.TryGetValue(querySource, out subSelectExpression) &&
                (!subSelectExpression.OrderBy.Any() ||
                 subSelectExpression.Limit != null))
            {
                subSelectExpression.PushDownSubquery().QuerySource = querySource;

                AddQuery(querySource, subSelectExpression);

                _subqueriesBySource.Remove(querySource);

                var shapedQueryMethodExpression
                    = new ShapedQueryFindingExpressionVisitor(QueryCompilationContext)
                      .Find(expression);

                var shaperLambda     = (LambdaExpression)shapedQueryMethodExpression.Arguments[2];
                var shaperMethodCall = (MethodCallExpression)shaperLambda.Body;

                var shaperMethod     = shaperMethodCall.Method;
                var shaperMethodArgs = shaperMethodCall.Arguments.ToList();

                if (!QueryCompilationContext.QuerySourceRequiresMaterialization(querySource) &&
                    shaperMethod.MethodIsClosedFormOf(RelationalEntityQueryableExpressionVisitor.CreateEntityMethodInfo))
                {
                    shaperMethod = RelationalEntityQueryableExpressionVisitor.CreateValueBufferMethodInfo;
                    shaperMethodArgs.RemoveRange(5, 5);
                }
                else
                {
                    subSelectExpression.ExplodeStarProjection();
                }

                var innerQuerySource = (IQuerySource)((ConstantExpression)shaperMethodArgs[0]).Value;

                foreach (var queryAnnotation
                         in QueryCompilationContext.QueryAnnotations
                         .Where(qa => qa.QuerySource == innerQuerySource))
                {
                    queryAnnotation.QuerySource = querySource;
                }

                shaperMethodArgs[0] = Expression.Constant(querySource);

                var querySourceReferenceExpression
                    = queryModel.SelectClause.Selector as QuerySourceReferenceExpression;

                if (querySourceReferenceExpression != null &&
                    querySourceReferenceExpression.ReferencedQuerySource == querySource)
                {
                    var subQueryModel = (itemsExpression as SubQueryExpression)?.QueryModel;

                    if (subQueryModel != null)
                    {
                        queryModel.SelectClause.Selector = subQueryModel.SelectClause.Selector;

                        QueryCompilationContext.QuerySourceMapping
                        .ReplaceMapping(
                            subQueryModel.MainFromClause,
                            QueryResultScope.GetResult(
                                QueryResultScopeParameter,
                                querySource,
                                shaperMethod.ReturnType.GenericTypeArguments[0]));
                    }
                }

                return(Expression.Call(
                           QueryCompilationContext.QueryMethodProvider.ShapedQueryMethod
                           .MakeGenericMethod(shaperMethod.ReturnType),
                           shapedQueryMethodExpression.Arguments[0],
                           shapedQueryMethodExpression.Arguments[1],
                           Expression.Lambda(
                               Expression.Call(shaperMethod, shaperMethodArgs),
                               shaperLambda.Parameters[0])));
            }

            return(expression);
        }
Example #4
0
        private Expression LiftSubQuery(
            IQuerySource querySource, Expression itemsExpression, QueryModel queryModel, Expression expression)
        {
            var subQueryExpression = itemsExpression as SubQueryExpression;

            if (subQueryExpression == null)
            {
                return(expression);
            }

            var subQueryModelVisitor
                = (RelationalQueryModelVisitor)QueryCompilationContext.CreateQueryModelVisitor(this);

            subQueryModelVisitor.VisitSubQueryModel(subQueryExpression.QueryModel);

            SelectExpression subSelectExpression = null;

            if (subQueryModelVisitor.Queries.Count == 1 &&
                !subQueryModelVisitor.RequiresClientFilter &&
                !subQueryModelVisitor.RequiresClientSelectMany &&
                !subQueryModelVisitor.RequiresClientProjection &&
                !subQueryModelVisitor.RequiresClientResultOperator)
            {
                subSelectExpression = subQueryModelVisitor.Queries.First();
            }

            if (subSelectExpression != null &&
                (!subSelectExpression.OrderBy.Any() ||
                 subSelectExpression.Limit != null) &&
                (QueryCompilationContext.IsCrossApplySupported ||
                 (!subSelectExpression.IsCorrelated() ||
                  !(querySource is AdditionalFromClause))))
            {
                subSelectExpression.PushDownSubquery().QuerySource = querySource;

                AddQuery(querySource, subSelectExpression);

                var shapedQueryMethodExpression
                    = new ShapedQueryFindingExpressionVisitor(QueryCompilationContext)
                      .Find(subQueryModelVisitor.Expression);

                var shaperLambda     = (LambdaExpression)shapedQueryMethodExpression.Arguments[2];
                var shaperMethodCall = (MethodCallExpression)shaperLambda.Body;

                var shaperMethod     = shaperMethodCall.Method;
                var shaperMethodArgs = shaperMethodCall.Arguments.ToList();

                if (!QueryCompilationContext.QuerySourceRequiresMaterialization(querySource) &&
                    shaperMethod.MethodIsClosedFormOf(RelationalEntityQueryableExpressionVisitor.CreateEntityMethodInfo))
                {
                    shaperMethod = RelationalEntityQueryableExpressionVisitor.CreateValueBufferMethodInfo;
                    shaperMethodArgs.RemoveRange(5, 5);
                }
                else
                {
                    subSelectExpression.ExplodeStarProjection();
                }

                var innerQuerySource = (IQuerySource)((ConstantExpression)shaperMethodArgs[0]).Value;

                foreach (var queryAnnotation
                         in QueryCompilationContext.QueryAnnotations
                         .Where(qa => qa.QuerySource == innerQuerySource))
                {
                    queryAnnotation.QuerySource = querySource;
                }

                shaperMethodArgs[0] = Expression.Constant(querySource);

                var querySourceReferenceExpression
                    = queryModel.SelectClause.Selector as QuerySourceReferenceExpression;

                if (querySourceReferenceExpression != null &&
                    querySourceReferenceExpression.ReferencedQuerySource == querySource)
                {
                    if (subQueryExpression.QueryModel != null)
                    {
                        queryModel.SelectClause.Selector = subQueryExpression.QueryModel.SelectClause.Selector;

                        QueryCompilationContext.QuerySourceMapping
                        .ReplaceMapping(
                            subQueryExpression.QueryModel.MainFromClause,
                            QueryResultScope.GetResult(
                                QueryResultScopeParameter,
                                querySource,
                                shaperMethod.ReturnType.GenericTypeArguments[0]));
                    }
                }

                return(Expression.Call(
                           QueryCompilationContext.QueryMethodProvider.ShapedQueryMethod
                           .MakeGenericMethod(shaperMethod.ReturnType),
                           shapedQueryMethodExpression.Arguments[0],
                           shapedQueryMethodExpression.Arguments[1],
                           Expression.Lambda(
                               Expression.Call(shaperMethod, shaperMethodArgs),
                               shaperLambda.Parameters[0])));
            }

            return(expression);
        }
Example #5
0
        public override void VisitGroupJoinClause(
            [NotNull] GroupJoinClause groupJoinClause, [NotNull] QueryModel queryModel, int index)
        {
            Check.NotNull(groupJoinClause, nameof(groupJoinClause));
            Check.NotNull(queryModel, nameof(queryModel));

            var outerKeySelector
                = ReplaceClauseReferences(groupJoinClause.JoinClause.OuterKeySelector, groupJoinClause);

            var innerExpression
                = CompileGroupJoinInnerSequenceExpression(groupJoinClause, queryModel);

            var innerSequenceType
                = innerExpression.Type.GetSequenceType();

            var innerItemParameter
                = Expression.Parameter(innerSequenceType);

            var innerElementScoped
                = innerSequenceType.IsConstructedGenericType &&
                  innerSequenceType.GetGenericTypeDefinition() == typeof(QueryResultScope <>);

            Type innerElementType;

            var querySourceMapping = _queryCompilationContext.QuerySourceMapping;

            if (innerElementScoped)
            {
                innerElementType = innerSequenceType.GetTypeInfo().GenericTypeArguments[0];

                querySourceMapping.AddMapping(
                    groupJoinClause.JoinClause,
                    QueryResultScope.GetResult(innerItemParameter, groupJoinClause.JoinClause, innerElementType));
            }
            else
            {
                innerElementType = innerSequenceType;

                querySourceMapping.AddMapping(groupJoinClause.JoinClause, innerItemParameter);
            }

            var innerKeySelector
                = ReplaceClauseReferences(groupJoinClause.JoinClause.InnerKeySelector, groupJoinClause);

            var innerItemsParameter
                = Expression.Parameter(innerExpression.Type);

            _expression
                = Expression.Call(
                      LinqOperatorProvider.GroupJoin.MakeGenericMethod(
                          typeof(QueryResultScope),
                          innerSequenceType,
                          outerKeySelector.Type,
                          typeof(QueryResultScope)),
                      _expression,
                      innerExpression,
                      Expression.Lambda(outerKeySelector, QueryResultScopeParameter),
                      Expression.Lambda(innerKeySelector, innerItemParameter),
                      Expression.Lambda(
                          QueryResultScope
                          .Create(
                              groupJoinClause,
                              innerElementScoped
                                    ? Expression.Call(
                                  LinqOperatorProvider.Select
                                  .MakeGenericMethod(
                                      innerSequenceType,
                                      innerElementType),
                                  innerItemsParameter,
                                  Expression.Lambda(
                                      QueryResultScope.GetResult(
                                          innerItemParameter,
                                          groupJoinClause.JoinClause,
                                          innerElementType),
                                      innerItemParameter))
                                    : (Expression)innerItemsParameter,
                              QueryResultScopeParameter),
                          QueryResultScopeParameter, innerItemsParameter));

            var expressionTypeInfo = _expression.Type.GetTypeInfo();

            querySourceMapping.AddMapping(
                groupJoinClause,
                QueryResultScope
                .GetResult(
                    QueryResultScopeParameter,
                    groupJoinClause,
                    expressionTypeInfo.GetGenericTypeDefinition()
                    .MakeGenericType(innerElementType)));
        }