Exemplo n.º 1
0
                public Expression GetGrouping(GroupByContext context)
                {
                    if (Configuration.Linq.GuardGrouping && !context._isGroupingGuardDisabled)
                    {
                        if (context.Element.Lambda.Parameters.Count == 1 &&
                            context.Element.Body == context.Element.Lambda.Parameters[0])
                        {
                            var ex = new LinqToDBException(
                                "You should explicitly specify selected fields for server-side GroupBy() call or add AsEnumerable() call before GroupBy() to perform client-side grouping.\n" +
                                "Set Configuration.Linq.GuardGrouping = false to disable this check.\n" +
                                "Additionally this guard exception can be disabled by extension GroupBy(...).DisableGuard().\n" +
                                "NOTE! By disabling this guard you accept additional Database Connection(s) to the server for processing such requests."
                                )
                            {
                                HelpLink = "https://github.com/linq2db/linq2db/issues/365"
                            };

                            throw ex;
                        }
                    }

                    var parameters = context.Builder.ParametersContext.CurrentSqlParameters
                                     .Select((p, i) => (p, i))
                                     .ToDictionary(_ => _.p.Expression, _ => _.i);
                    var paramArray = Expression.Parameter(typeof(object[]), "ps");

                    var groupExpression = context._sequenceExpr.Transform(
                        (parameters, paramArray),
Exemplo n.º 2
0
        protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo)
        {
            var sequenceExpr    = methodCall.Arguments[0];
            var sequence        = builder.BuildSequence(new BuildInfo(buildInfo, sequenceExpr));
            var groupingType    = methodCall.Type.GetGenericArguments()[0];
            var keySelector     = (LambdaExpression)methodCall.Arguments[1].Unwrap();
            var elementSelector = (LambdaExpression)methodCall.Arguments[2].Unwrap();

            if (methodCall.Arguments[0].NodeType == ExpressionType.Call)
            {
                var call = (MethodCallExpression)methodCall.Arguments[0];

                if (call.Method.Name == "Select")
                {
                    var type = ((LambdaExpression)call.Arguments[1].Unwrap()).Body.Type;

                    if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(ExpressionBuilder.GroupSubQuery <,>))
                    {
                        sequence = new SubQueryContext(sequence);
                    }
                }
            }

            var key      = new KeyContext(buildInfo.Parent, keySelector, sequence);
            var groupSql = builder.ConvertExpressions(key, keySelector.Body.Unwrap(), ConvertFlags.Key);

            if (sequence.SqlQuery.Select.IsDistinct ||
                sequence.SqlQuery.GroupBy.Items.Count > 0 ||
                groupSql.Any(_ => !(_.Sql is SqlField || _.Sql is SqlQuery.Column)))
            {
                sequence = new SubQueryContext(sequence);
                key      = new KeyContext(buildInfo.Parent, keySelector, sequence);
                groupSql = builder.ConvertExpressions(key, keySelector.Body.Unwrap(), ConvertFlags.Key);
            }

            //sequence.SqlQuery.GroupBy.Items.Clear();

            foreach (var sql in groupSql)
            {
                sequence.SqlQuery.GroupBy.Expr(sql.Sql);
            }

            new QueryVisitor().Visit(sequence.SqlQuery.From, e =>
            {
                if (e.ElementType == QueryElementType.JoinedTable)
                {
                    var jt = (SqlQuery.JoinedTable)e;
                    if (jt.JoinType == SqlQuery.JoinType.Inner)
                    {
                        jt.IsWeak = false;
                    }
                }
            });

            var element = new SelectContext(buildInfo.Parent, elementSelector, sequence /*, key*/);
            var groupBy = new GroupByContext(buildInfo.Parent, sequenceExpr, groupingType, sequence, key, element);

            return(groupBy);
        }
Exemplo n.º 3
0
 public ExtraEntry(int?skip, int?take, IEnumerable <PropertyOrder> orders, SelectContext selectContext, GroupByContext groupByContext)
 {
     Skip           = skip;
     Take           = take;
     Orders         = orders;
     SelectContext  = selectContext;
     GroupByContext = groupByContext;
 }
Exemplo n.º 4
0
 public SelectCommandContext(SchemaMetaData schemaMetaData, string sql, ParameterContext parameterContext, SelectCommand sqlCommand) : base(sqlCommand)
 {
     _tablesContext      = new TablesContext(sqlCommand.GetSimpleTableSegments());
     _groupByContext     = new GroupByContextEngine().CreateGroupByContext(sqlCommand);
     _orderByContext     = new OrderByContextEngine().CreateOrderBy(sqlCommand, _groupByContext);
     _projectionsContext = new ProjectionsContextEngine(schemaMetaData).CreateProjectionsContext(sql, sqlCommand, _groupByContext, _orderByContext);
     _paginationContext  = new PaginationContextEngine().CreatePaginationContext(sqlCommand, _projectionsContext, parameterContext);
     _containsSubQuery   = ContainsSubQuery();
 }
Exemplo n.º 5
0
 // TODO to be remove, for test case only
 public SelectCommandContext(SelectCommand sqlCommand, GroupByContext groupByContext,
                             OrderByContext orderByContext, ProjectionsContext projectionsContext, PaginationContext paginationContext) : base(sqlCommand)
 {
     _tablesContext           = new TablesContext(sqlCommand.GetSimpleTableSegments());
     this._groupByContext     = groupByContext;
     this._orderByContext     = orderByContext;
     this._projectionsContext = projectionsContext;
     this._paginationContext  = paginationContext;
     _containsSubQuery        = ContainsSubQuery();
 }
Exemplo n.º 6
0
 public ReWriteResult(IQueryable <T> originalQueryable, IQueryable <T> reWriteQueryable, int?skip, int?take, IEnumerable <PropertyOrder> orders, SelectContext selectContext, GroupByContext groupByContext)
 {
     OriginalQueryable = originalQueryable;
     ReWriteQueryable  = reWriteQueryable;
     Skip           = skip;
     Take           = take;
     Orders         = orders;
     SelectContext  = selectContext;
     GroupByContext = groupByContext;
 }
Exemplo n.º 7
0
                public Expression GetGrouping(GroupByContext context)
                {
                    var keyParam = Expression.Parameter(typeof(TKey), "key");

// ReSharper disable AssignNullToNotNullAttribute

                    var expr = Expression.Call(
                        null,
                        ReflectionHelper.Expressor <object> .MethodExpressor(_ => Queryable.Where(null, (Expression <Func <TSource, bool> >)null)),
                        context._sequenceExpr,
                        Expression.Lambda <Func <TSource, bool> >(
                            Expression.Equal(context._key.Lambda.Body, keyParam),
                            new[] { context._key.Lambda.Parameters[0] }));

                    expr = Expression.Call(
                        null,
                        ReflectionHelper.Expressor <object> .MethodExpressor(_ => Queryable.Select(null, (Expression <Func <TSource, TElement> >)null)),
                        expr,
                        context._element.Lambda);

// ReSharper restore AssignNullToNotNullAttribute

                    var lambda = Expression.Lambda <Func <IDataContext, TKey, IQueryable <TElement> > >(
                        Expression.Convert(expr, typeof(IQueryable <TElement>)),
                        Expression.Parameter(typeof(IDataContext), "ctx"),
                        keyParam);

                    var itemReader = CompiledQuery.Compile(lambda);
                    var keyExpr    = context._key.BuildExpression(null, 0);
                    var keyReader  = Expression.Lambda <Func <QueryContext, IDataContext, IDataReader, Expression, object[], TKey> >(
                        keyExpr,
                        new []
                    {
                        ExpressionBuilder.ContextParam,
                        ExpressionBuilder.DataContextParam,
                        ExpressionBuilder.DataReaderParam,
                        ExpressionBuilder.ExpressionParam,
                        ExpressionBuilder.ParametersParam,
                    });

                    return(Expression.Call(
                               null,
                               ReflectionHelper.Expressor <object> .MethodExpressor(_ => GetGrouping(null, null, null, null, null, null, null)),
                               new Expression[]
                    {
                        ExpressionBuilder.ContextParam,
                        ExpressionBuilder.DataContextParam,
                        ExpressionBuilder.DataReaderParam,
                        ExpressionBuilder.ExpressionParam,
                        ExpressionBuilder.ParametersParam,
                        Expression.Constant(keyReader.Compile()),
                        Expression.Constant(itemReader),
                    }));
                }
Exemplo n.º 8
0
        internal override List <GremlinVariable> FetchAllTableVars()
        {
            List <GremlinVariable> variableList = new List <GremlinVariable>()
            {
                this
            };

            variableList.AddRange(GroupByContext.FetchAllTableVars());
            variableList.AddRange(ProjectByContext.FetchAllTableVars());
            return(variableList);
        }
Exemplo n.º 9
0
		protected override IParseContext ParseMethodCall(ExpressionParser parser, IParseContext parent, MethodCallExpression methodCall, SqlQuery sqlQuery)
		{
			var sequence        = parser.ParseSequence(parent, methodCall.Arguments[0], sqlQuery);
			var sequenceExpr    = methodCall.Arguments[0];
			var groupingType    = methodCall.Type.GetGenericArguments()[0];
			var keySelector     = (LambdaExpression)methodCall.Arguments[1].Unwrap();
			var elementSelector = (LambdaExpression)methodCall.Arguments[2].Unwrap();

			if (methodCall.Arguments[0].NodeType == ExpressionType.Call)
			{
				var call = (MethodCallExpression)methodCall.Arguments[0];

				if (call.Method.Name == "Select")
				{
					var type = ((LambdaExpression)call.Arguments[1].Unwrap()).Body.Type;

					if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(ExpressionParser.GroupSubQuery<,>))
					{
						sequence = new SubQueryContext(sequence);
					}
				}
			}

			var key      = new KeyContext(keySelector, sequence);
			var groupSql = parser.ParseExpressions(key, keySelector.Body.Unwrap(), ConvertFlags.Key);

			if (groupSql.Any(_ => !(_.Sql is SqlField || _.Sql is SqlQuery.Column)))
			{
				sequence = new SubQueryContext(sequence);
				key      = new KeyContext(keySelector, sequence);
				groupSql = parser.ParseExpressions(key, keySelector.Body.Unwrap(), ConvertFlags.Key);
			}

			sequence.SqlQuery.GroupBy.Items.Clear();

			foreach (var sql in groupSql)
				sequence.SqlQuery.GroupBy.Expr(sql.Sql);

			new QueryVisitor().Visit(sequence.SqlQuery.From, e =>
			{
				if (e.ElementType == QueryElementType.JoinedTable)
				{
					var jt = (SqlQuery.JoinedTable)e;
					if (jt.JoinType == SqlQuery.JoinType.Inner)
						jt.IsWeak = false;
				}
			});

			var element = new SelectContext (elementSelector, sequence);
			var groupBy = new GroupByContext(sequenceExpr, groupingType, sequence, key, element);

			return groupBy;
		}
        public override WTableReference ToTableReference()
        {
            List <WScalarExpression> parameters = new List <WScalarExpression>();

            parameters.Add(SqlUtil.GetValueExpr(SideEffectKey));
            parameters.Add(SqlUtil.GetScalarSubquery(GroupByContext.ToSelectQueryBlock()));
            parameters.Add(SqlUtil.GetScalarSubquery(ProjectByContext.ToSelectQueryBlock()));
            var tableRef = SqlUtil.GetFunctionTableReference(GremlinKeyword.func.Group, parameters, GetVariableName());

            ((WGroupTableReference)tableRef).IsProjectingACollection = IsProjectingACollection;
            return(SqlUtil.GetCrossApplyTableReference(tableRef));
        }
        internal override List <GremlinVariable> FetchVarsFromCurrAndChildContext()
        {
            List <GremlinVariable> variableList = new List <GremlinVariable>();

            if (GroupByContext != null)
            {
                variableList.AddRange(GroupByContext.FetchVarsFromCurrAndChildContext());
            }
            if (ProjectByContext != null)
            {
                variableList.AddRange(ProjectByContext.FetchVarsFromCurrAndChildContext());
            }
            return(variableList);
        }
        public StreamMergeContext(IQueryable <T> source, IEnumerable <RouteResult> routeResults,
                                  IShardingParallelDbContextFactory shardingParallelDbContextFactory, IShardingScopeFactory shardingScopeFactory)
        {
            _shardingParallelDbContextFactory = shardingParallelDbContextFactory;
            _shardingScopeFactory             = shardingScopeFactory;
            _source      = source;
            RouteResults = routeResults;
            var reWriteResult = new ReWriteEngine <T>(source).ReWrite();

            Skip           = reWriteResult.Skip;
            Take           = reWriteResult.Take;
            Orders         = reWriteResult.Orders ?? Enumerable.Empty <PropertyOrder>();
            SelectContext  = reWriteResult.SelectContext;
            GroupByContext = reWriteResult.GroupByContext;
            _reWriteSource = reWriteResult.ReWriteQueryable;
        }
Exemplo n.º 13
0
        public OrderByContext CreateOrderBy(SelectCommand selectCommand, GroupByContext groupByContext)
        {
            if (null == selectCommand.OrderBy || !selectCommand.OrderBy.GetOrderByItems().Any())
            {
                OrderByContext orderByContext = CreateOrderByContextForDistinctRowWithoutGroupBy(selectCommand, groupByContext);
                return(null != orderByContext ? orderByContext : new OrderByContext(groupByContext.GetItems(), groupByContext.GetItems().Any()));
            }

            ICollection <OrderByItem> orderByItems = new LinkedList <OrderByItem>();

            foreach (var orderByItemSegment in selectCommand.OrderBy.GetOrderByItems())
            {
                OrderByItem orderByItem = new OrderByItem(orderByItemSegment);
                if (orderByItemSegment is IndexOrderByItemSegment indexOrderByItemSegment)
                {
                    orderByItem.SetIndex(indexOrderByItemSegment.GetColumnIndex());
                }

                orderByItems.Add(orderByItem);
            }

            return(new OrderByContext(orderByItems, false));
        }
Exemplo n.º 14
0
                public Expression GetGrouping(GroupByContext context)
                {
                    var parameters = context.Builder.CurrentSqlParameters
                                     .Select((p, i) => new { p, i })
                                     .ToDictionary(_ => _.p.Expression, _ => _.i);
                    var paramArray = Expression.Parameter(typeof(object[]), "ps");

                    var groupExpression = context._sequenceExpr.Transform(e =>
                    {
                        int idx;

                        if (parameters.TryGetValue(e, out idx))
                        {
                            return
                            (Expression.Convert(
                                 Expression.ArrayIndex(paramArray, Expression.Constant(idx)),
                                 e.Type));
                        }

                        return(e);
                    });

                    var keyParam = Expression.Parameter(typeof(TKey), "key");

// ReSharper disable AssignNullToNotNullAttribute

                    var expr = Expression.Call(
                        null,
                        MemberHelper.MethodOf(() => Queryable.Where(null, (Expression <Func <TSource, bool> >)null)),
                        groupExpression,
                        Expression.Lambda <Func <TSource, bool> >(
                            Expression.Equal(context._key.Lambda.Body, keyParam), context._key.Lambda.Parameters[0]));

                    expr = Expression.Call(
                        null,
                        MemberHelper.MethodOf(() => Queryable.Select(null, (Expression <Func <TSource, TElement> >)null)),
                        expr,
                        context._element.Lambda);

// ReSharper restore AssignNullToNotNullAttribute

                    var lambda = Expression.Lambda <Func <IDataContext, TKey, object[], IQueryable <TElement> > >(
                        Expression.Convert(expr, typeof(IQueryable <TElement>)),
                        Expression.Parameter(typeof(IDataContext), "ctx"),
                        keyParam,
                        paramArray);

                    var itemReader      = CompiledQuery.Compile(lambda);
                    var keyExpr         = context._key.BuildExpression(null, 0);
                    var dataReaderLocal = context.Builder.DataReaderLocal;

                    if (!Common.Configuration.AvoidSpecificDataProviderAPI &&
                        keyExpr.Find(e => e == dataReaderLocal) != null)
                    {
                        keyExpr = Expression.Block(
                            new[] { context.Builder.DataReaderLocal },
                            Expression.Assign(dataReaderLocal,
                                              Expression.Convert(ExpressionBuilder.DataReaderParam,
                                                                 context.Builder.DataContextInfo.DataContext.DataReaderType)), keyExpr);
                    }

                    var keyReader = Expression
                                    .Lambda <Func <QueryContext, IDataContext, IDataReader, Expression, object[], TKey> >(
                        keyExpr, ExpressionBuilder.ContextParam, ExpressionBuilder.DataContextParam,
                        ExpressionBuilder.DataReaderParam, ExpressionBuilder.ExpressionParam,
                        ExpressionBuilder.ParametersParam);

                    return(Expression.Call(
                               null,
                               MemberHelper.MethodOf(() => GetGrouping(null, null, null, null, null, null, null, null)),
                               ExpressionBuilder.ContextParam, ExpressionBuilder.DataContextParam,
                               ExpressionBuilder.DataReaderParam, Expression.Constant(context.Builder.CurrentSqlParameters),
                               ExpressionBuilder.ExpressionParam, ExpressionBuilder.ParametersParam,
                               Expression.Constant(keyReader.Compile()), Expression.Constant(itemReader)));
                }
Exemplo n.º 15
0
                public Expression GetGrouping(GroupByContext context)
                {
                    if (Configuration.Linq.GuardGrouping)
                    {
                        if (context._element.Lambda.Parameters.Count == 1 &&
                            context._element.Body == context._element.Lambda.Parameters[0])
                        {
                            var ex = new LinqToDBException(
                                "You should explicitly specify selected fields for server-side GroupBy() call or add AsEnumerable() call before GroupBy() to perform client-side grouping.\n" +
                                "Set Configuration.Linq.GuardGrouping = false to disable this check."
                                )
                            {
                                HelpLink = "https://github.com/linq2db/linq2db/issues/365"
                            };

                            throw ex;
                        }
                    }

                    var parameters = context.Builder.CurrentSqlParameters
                                     .Select((p, i) => new { p, i })
                                     .ToDictionary(_ => _.p.Expression, _ => _.i);
                    var paramArray = Expression.Parameter(typeof(object[]), "ps");

                    var groupExpression = context._sequenceExpr.Transform(e =>
                    {
                        int idx;

                        if (parameters.TryGetValue(e, out idx))
                        {
                            return
                            (Expression.Convert(
                                 Expression.ArrayIndex(paramArray, Expression.Constant(idx)),
                                 e.Type));
                        }

                        return(e);
                    });

                    var keyParam = Expression.Parameter(typeof(TKey), "key");

// ReSharper disable AssignNullToNotNullAttribute

                    var expr = Expression.Call(
                        null,
                        MemberHelper.MethodOf(() => Queryable.Where(null, (Expression <Func <TSource, bool> >)null)),
                        groupExpression,
                        Expression.Lambda <Func <TSource, bool> >(
                            ExpressionBuilder.Equal(context.Builder.MappingSchema, context._key.Lambda.Body, keyParam),
                            new[] { context._key.Lambda.Parameters[0] }));

                    expr = Expression.Call(
                        null,
                        MemberHelper.MethodOf(() => Queryable.Select(null, (Expression <Func <TSource, TElement> >)null)),
                        expr,
                        context._element.Lambda);

// ReSharper restore AssignNullToNotNullAttribute

                    var lambda = Expression.Lambda <Func <IDataContext, TKey, object[], IQueryable <TElement> > >(
                        Expression.Convert(expr, typeof(IQueryable <TElement>)),
                        Expression.Parameter(typeof(IDataContext), "ctx"),
                        keyParam,
                        paramArray);

                    var itemReader      = CompiledQuery.Compile(lambda);
                    var keyExpr         = context._key.BuildExpression(null, 0, false);
                    var dataReaderLocal = context.Builder.DataReaderLocal;

                    if (!Configuration.AvoidSpecificDataProviderAPI && keyExpr.Find(e => e == dataReaderLocal) != null)
                    {
                        keyExpr = Expression.Block(
                            new[] { context.Builder.DataReaderLocal },
                            new[]
                        {
                            Expression.Assign(dataReaderLocal, Expression.Convert(ExpressionBuilder.DataReaderParam, context.Builder.DataContext.DataReaderType)),
                            keyExpr
                        });
                    }

                    var keyReader = Expression.Lambda <Func <IQueryRunner, IDataContext, IDataReader, Expression, object[], TKey> >(
                        keyExpr,
                        new []
                    {
                        ExpressionBuilder.QueryRunnerParam,
                        ExpressionBuilder.DataContextParam,
                        ExpressionBuilder.DataReaderParam,
                        ExpressionBuilder.ExpressionParam,
                        ExpressionBuilder.ParametersParam
                    });

                    return(Expression.Call(
                               null,
                               MemberHelper.MethodOf(() => GetGrouping(null, null, null, null, null, null, null, null)),
                               new Expression[]
                    {
                        ExpressionBuilder.QueryRunnerParam,
                        ExpressionBuilder.DataContextParam,
                        ExpressionBuilder.DataReaderParam,
                        Expression.Constant(context.Builder.CurrentSqlParameters),
                        ExpressionBuilder.ExpressionParam,
                        ExpressionBuilder.ParametersParam,
                        Expression.Constant(keyReader.Compile()),
                        Expression.Constant(itemReader)
                    }));
                }
Exemplo n.º 16
0
 /// <summary>
 ///     Returns a Slinq that enumerates the key, value groupings contained in the lookup, with the values returned in Linked form.
 ///     As the groupings are enumerated, ownership of the values in each grouping is transferred to the owner of the grouping, who is
 ///     responsible for their disposal.
 ///     When the enumeration is complete, the lookup and any unenumerated values it contains are added to the disposal queue.
 /// </summary>
 public Slinq <Grouping <K, T>, GroupByContext <K, T> > SlinqLinkedAndDispose()
 {
     return(GroupByContext <K, T> .SlinqLinked(this, true));
 }
Exemplo n.º 17
0
 /// <summary>
 ///     Returns a Slinq that enumerates the key, value groupings contained in the lookup, with the values returned in Linked form.
 ///     Ownership of the lookup and any values it contains is retained by the caller.
 /// </summary>
 public Slinq <Grouping <K, T>, GroupByContext <K, T> > SlinqLinkedAndKeep()
 {
     return(GroupByContext <K, T> .SlinqLinked(this, false));
 }
Exemplo n.º 18
0
        private OrderByContext CreateOrderByContextForDistinctRowWithoutGroupBy(SelectCommand selectCommand, GroupByContext groupByContext)
        {
            if (!groupByContext.GetItems().Any() && selectCommand.Projections.IsDistinctRow())
            {
                int index = 0;
                ICollection <OrderByItem> orderByItems = new LinkedList <OrderByItem>();
                foreach (var projectionSegment in selectCommand.Projections.GetProjections())
                {
                    if (projectionSegment is ColumnProjectionSegment columnProjectionSegment)
                    {
                        var         columnOrderByItemSegment = new ColumnOrderByItemSegment(columnProjectionSegment.GetColumn(), OrderDirectionEnum.ASC);
                        OrderByItem item = new OrderByItem(columnOrderByItemSegment);
                        item.SetIndex(index);
                        orderByItems.Add(item);
                        index++;
                    }
                }

                if (orderByItems.Any())
                {
                    return(new OrderByContext(orderByItems, true));
                }
            }

            return(null);
        }
Exemplo n.º 19
0
        protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo)
        {
            var sequenceExpr             = methodCall.Arguments[0];
            var wrapSequence             = false;
            LambdaExpression?groupingKey = null;
            var groupingKind             = GroupingType.Default;

            if (sequenceExpr.NodeType == ExpressionType.Call)
            {
                var call = (MethodCallExpression)methodCall.Arguments[0];

                if (call.IsQueryable("Select"))
                {
                    var selectParam = (LambdaExpression)call.Arguments[1].Unwrap();
                    var type        = selectParam.Body.Type;

                    if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(ExpressionBuilder.GroupSubQuery <,>))
                    {
                        wrapSequence = true;

                        var selectParamBody = selectParam.Body.Unwrap();
                        MethodCallExpression?groupingMethod = null;
                        if (selectParamBody is MemberInitExpression mi)
                        {
                            var assignment = mi.Bindings.OfType <MemberAssignment>().FirstOrDefault(m => m.Member.Name == "Key");
                            if (assignment?.Expression.NodeType == ExpressionType.Call)
                            {
                                var mc = (MethodCallExpression)assignment.Expression;
                                if (mc.IsSameGenericMethod(Methods.LinqToDB.GroupBy.Rollup, Methods.LinqToDB.GroupBy.Cube, Methods.LinqToDB.GroupBy.GroupingSets))
                                {
                                    groupingMethod = mc;
                                    groupingKey    = (LambdaExpression)mc.Arguments[0].Unwrap();
                                    if (mc.IsSameGenericMethod(Methods.LinqToDB.GroupBy.Rollup))
                                    {
                                        groupingKind = GroupingType.Rollup;
                                    }
                                    else if (mc.IsSameGenericMethod(Methods.LinqToDB.GroupBy.Cube))
                                    {
                                        groupingKind = GroupingType.Cube;
                                    }
                                    else if (mc.IsSameGenericMethod(Methods.LinqToDB.GroupBy.GroupingSets))
                                    {
                                        groupingKind = GroupingType.GroupBySets;
                                    }
                                    else
                                    {
                                        throw new InvalidOperationException();
                                    }
                                }
                            }
                        }

                        if (groupingMethod != null && groupingKey != null)
                        {
                            sequenceExpr = sequenceExpr.Replace(groupingMethod, groupingKey.Body.Unwrap());
                        }
                    }
                }
            }

            var sequence    = builder.BuildSequence(new BuildInfo(buildInfo, sequenceExpr));
            var keySequence = sequence;

            var groupingType    = methodCall.Type.GetGenericArguments()[0];
            var keySelector     = (LambdaExpression)methodCall.Arguments[1].Unwrap() !;
            var elementSelector = (LambdaExpression)methodCall.Arguments[2].Unwrap() !;

            if (wrapSequence)
            {
                sequence = new SubQueryContext(sequence);
            }

            sequence = new SubQueryContext(sequence);
            var key = new KeyContext(buildInfo.Parent, keySelector, sequence);

            if (groupingKind != GroupingType.GroupBySets)
            {
                var groupSql = builder.ConvertExpressions(key, keySelector.Body.Unwrap(), ConvertFlags.Key, null);

                var allowed = groupSql.Where(s => !QueryHelper.IsConstant(s.Sql));

                foreach (var sql in allowed)
                {
                    sequence.SelectQuery.GroupBy.Expr(sql.Sql);
                }
            }
            else
            {
                var goupingSetBody = groupingKey !.Body;
                var groupingSets   = EnumGroupingSets(goupingSetBody).ToArray();
                if (groupingSets.Length == 0)
                {
                    throw new LinqException($"Invalid groping sets expression '{goupingSetBody}'.");
                }

                foreach (var groupingSet in groupingSets)
                {
                    var groupSql = builder.ConvertExpressions(keySequence, groupingSet, ConvertFlags.Key, null);
                    sequence.SelectQuery.GroupBy.Items.Add(
                        new SqlGroupingSet(groupSql.Select(s => keySequence.SelectQuery.Select.AddColumn(s.Sql))));
                }
            }

            sequence.SelectQuery.GroupBy.GroupingType = groupingKind;

            var element = new SelectContext(buildInfo.Parent, elementSelector, sequence /*, key*/);
            var groupBy = new GroupByContext(buildInfo.Parent, sequenceExpr, groupingType, sequence, key, element, builder.IsGroupingGuardDisabled);

            Debug.WriteLine("BuildMethodCall GroupBy:\n" + groupBy.SelectQuery);

            return(groupBy);
        }
Exemplo n.º 20
0
                public Expression GetGrouping(GroupByContext context)
                {
                    if (Configuration.Linq.GuardGrouping && !context._isGroupingGuardDisabled)
                    {
                        if (context.Element.Lambda.Parameters.Count == 1 &&
                            context.Element.Body == context.Element.Lambda.Parameters[0])
                        {
                            var ex = new LinqToDBException(
                                "You should explicitly specify selected fields for server-side GroupBy() call or add AsEnumerable() call before GroupBy() to perform client-side grouping.\n" +
                                "Set Configuration.Linq.GuardGrouping = false to disable this check.\n" +
                                "Additionally this guard exception can be disabled by extension GroupBy(...).DisableGuard().\n" +
                                "NOTE! By disabling this guard you accept additional Database Connection(s) to the server for processing such requests."
                                )
                            {
                                HelpLink = "https://github.com/linq2db/linq2db/issues/365"
                            };

                            throw ex;
                        }
                    }

                    var parameters = context.Builder.CurrentSqlParameters
                                     .Select((p, i) => new { p, i })
                                     .ToDictionary(_ => _.p.Expression, _ => _.i);
                    var paramArray = Expression.Parameter(typeof(object[]), "ps");

                    var groupExpression = context._sequenceExpr.Transform(e =>
                    {
                        if (parameters.TryGetValue(e, out var idx))
                        {
                            return
                            (Expression.Convert(
                                 Expression.ArrayIndex(paramArray, Expression.Constant(idx)),
                                 e.Type));
                        }

                        return(e);
                    });

                    var keyParam = Expression.Parameter(typeof(TKey), "key");

// ReSharper disable AssignNullToNotNullAttribute

                    var expr = Expression.Call(
                        null,
                        MemberHelper.MethodOf(() => Queryable.Where(null, (Expression <Func <TSource, bool> >)null !)),
                        groupExpression,
                        Expression.Lambda <Func <TSource, bool> >(
                            ExpressionBuilder.Equal(context.Builder.MappingSchema, context._key.Lambda.Body, keyParam),
                            new[] { context._key.Lambda.Parameters[0] }));

                    expr = Expression.Call(
                        null,
                        MemberHelper.MethodOf(() => Queryable.Select(null, (Expression <Func <TSource, TElement> >)null !)),
                        expr,
                        context.Element.Lambda);

// ReSharper restore AssignNullToNotNullAttribute

                    var lambda = Expression.Lambda <Func <IDataContext, TKey, object?[]?, IQueryable <TElement> > >(
                        Expression.Convert(expr, typeof(IQueryable <TElement>)),
                        Expression.Parameter(typeof(IDataContext), "ctx"),
                        keyParam,
                        paramArray);

                    var itemReader = CompiledQuery.Compile(lambda);
                    var keyExpr    = context._key.BuildExpression(null, 0, false);

                    var keyReader = Expression.Lambda <Func <IQueryRunner, IDataContext, IDataReader, Expression, object?[]?, TKey> >(
                        keyExpr,
                        new []
                    {
                        ExpressionBuilder.QueryRunnerParam,
                        ExpressionBuilder.DataContextParam,
                        ExpressionBuilder.DataReaderParam,
                        ExpressionBuilder.ExpressionParam,
                        ExpressionBuilder.ParametersParam
                    });

                    return(Expression.Call(
                               null,
                               MemberHelper.MethodOf(() => GetGrouping(null !, null !, null !, null !, null !, null !, null !, null !)),
                               new Expression[]
                    {
                        ExpressionBuilder.QueryRunnerParam,
                        ExpressionBuilder.DataContextParam,
                        ExpressionBuilder.DataReaderParam,
                        Expression.Constant(context.Builder.CurrentSqlParameters),
                        ExpressionBuilder.ExpressionParam,
                        ExpressionBuilder.ParametersParam,
                        keyReader,
                        Expression.Constant(itemReader)
                    }));
                }
 private ICollection <IProjection> GetDerivedGroupByColumns(ICollection <IProjection> projections, GroupByContext groupByContext, SelectCommand selectCommand)
 {
     return(GetDerivedOrderColumns(projections, groupByContext.GetItems(), DerivedColumn.Get(DerivedColumnEnum.GROUP_BY_ALIAS), selectCommand));
 }
Exemplo n.º 22
0
                public Expression GetGrouping(GroupByContext context)
                {
                    var parameters = context.Builder.CurrentSqlParameters
                                     .Select((p, i) => new { p, i })
                                     .ToDictionary(_ => _.p.Expression, _ => _.i);
                    var paramArray = Expression.Parameter(typeof(object[]), "ps");

                    var groupExpression = context._sequenceExpr.Convert(e =>
                    {
                        int idx;

                        if (parameters.TryGetValue(e, out idx))
                        {
                            return
                            (Expression.Convert(
                                 Expression.ArrayIndex(paramArray, Expression.Constant(idx)),
                                 e.Type));
                        }

                        return(e);
                    });

                    var keyParam = Expression.Parameter(typeof(TKey), "key");

// ReSharper disable AssignNullToNotNullAttribute

                    var expr = Expression.Call(
                        null,
                        ReflectionHelper.Expressor <object> .MethodExpressor(_ => Queryable.Where(null, (Expression <Func <TSource, bool> >)null)),
                        groupExpression,
                        Expression.Lambda <Func <TSource, bool> >(
                            Expression.Equal(context._key.Lambda.Body, keyParam),
                            new[] { context._key.Lambda.Parameters[0] }));

                    expr = Expression.Call(
                        null,
                        ReflectionHelper.Expressor <object> .MethodExpressor(_ => Queryable.Select(null, (Expression <Func <TSource, TElement> >)null)),
                        expr,
                        context._element.Lambda);

// ReSharper restore AssignNullToNotNullAttribute

                    var lambda = Expression.Lambda <Func <IDataContext, TKey, object[], IQueryable <TElement> > >(
                        Expression.Convert(expr, typeof(IQueryable <TElement>)),
                        Expression.Parameter(typeof(IDataContext), "ctx"),
                        keyParam,
                        paramArray);

                    var itemReader = CompiledQuery.Compile(lambda);
                    var keyExpr    = context._key.BuildExpression(null, 0);
                    var keyReader  = Expression.Lambda <Func <QueryContext, IDataContext, IDataReader, Expression, object[], TKey> >(
                        keyExpr,
                        new []
                    {
                        ExpressionBuilder.ContextParam,
                        ExpressionBuilder.DataContextParam,
                        ExpressionBuilder.DataReaderParam,
                        ExpressionBuilder.ExpressionParam,
                        ExpressionBuilder.ParametersParam,
                    });

                    return(Expression.Call(
                               null,
                               ReflectionHelper.Expressor <object> .MethodExpressor(_ => GetGrouping(null, null, null, null, null, null, null, null)),
                               new Expression[]
                    {
                        ExpressionBuilder.ContextParam,
                        ExpressionBuilder.DataContextParam,
                        ExpressionBuilder.DataReaderParam,
                        Expression.Constant(context.Builder.CurrentSqlParameters),
                        ExpressionBuilder.ExpressionParam,
                        ExpressionBuilder.ParametersParam,
                        Expression.Constant(keyReader.Compile()),
                        Expression.Constant(itemReader),
                    }));
                }
        /// <summary>
        /// Create projections context.
        /// </summary>
        /// <param name="sql"></param>
        /// <param name="selectCommand"></param>
        /// <param name="groupByContext"></param>
        /// <param name="orderByContext"></param>
        /// <returns></returns>
        public ProjectionsContext CreateProjectionsContext(string sql, SelectCommand selectCommand, GroupByContext groupByContext, OrderByContext orderByContext)
        {
            ProjectionsSegment        projectionsSegment = selectCommand.Projections;
            ICollection <IProjection> projections        = GetProjections(sql, selectCommand.GetSimpleTableSegments(), projectionsSegment);
            ProjectionsContext        result             = new ProjectionsContext(projectionsSegment.GetStartIndex(), projectionsSegment.GetStopIndex(), projectionsSegment.IsDistinctRow(), projections);

            result.GetProjections().AddAll(GetDerivedGroupByColumns(projections, groupByContext, selectCommand));
            result.GetProjections().AddAll(GetDerivedOrderByColumns(projections, orderByContext, selectCommand));
            return(result);
        }
Exemplo n.º 24
0
        protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo)
        {
            var sequenceExpr    = methodCall.Arguments[0];
            var sequence        = builder.BuildSequence(new BuildInfo(buildInfo, sequenceExpr));
            var groupingType    = methodCall.Type.GetGenericArgumentsEx()[0];
            var keySelector     = (LambdaExpression)methodCall.Arguments[1].Unwrap();
            var elementSelector = (LambdaExpression)methodCall.Arguments[2].Unwrap();

            if (methodCall.Arguments[0].NodeType == ExpressionType.Call)
            {
                var call = (MethodCallExpression)methodCall.Arguments[0];

                if (call.Method.Name == "Select")
                {
                    var type = ((LambdaExpression)call.Arguments[1].Unwrap()).Body.Type;

                    if (type.IsGenericTypeEx() && type.GetGenericTypeDefinition() == typeof(ExpressionBuilder.GroupSubQuery <,>))
                    {
                        sequence = new SubQueryContext(sequence);
                    }
                }
            }

            var key      = new KeyContext(buildInfo.Parent, keySelector, sequence);
            var groupSql = builder.ConvertExpressions(key, keySelector.Body.Unwrap(), ConvertFlags.Key);

            if (sequence.SelectQuery.Select.IsDistinct ||
                sequence.SelectQuery.GroupBy.Items.Count > 0 ||
                groupSql.Any(_ => !(_.Sql is SqlField || _.Sql is SelectQuery.Column)))
            {
                sequence = new SubQueryContext(sequence);
                key      = new KeyContext(buildInfo.Parent, keySelector, sequence);
                groupSql = builder.ConvertExpressions(key, keySelector.Body.Unwrap(), ConvertFlags.Key);
            }
            else if (groupSql.Length == 1 && groupSql.Any(_ => _.Sql is SelectQuery.Column))
            {
                //var columns = (SelectQuery.Column) groupSql[0]. Sql;
                //var value = columns.Expression as SqlValue;
                //if (value != null && value.SystemType.Name.Equals("String"))
                //{
                //            // var allColumns = value.Value.ToString().Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                //             sequence.SelectQuery.GroupBy.Items.Add(new SqlField {Name = value.Value.ToString(),PhysicalName ="columnString" });
                //         }
            }

            foreach (var sql in groupSql)
            {
                sequence.SelectQuery.GroupBy.Expr(sql.Sql);
            }

            new QueryVisitor().Visit(sequence.SelectQuery.From, (e, table_cloumn) =>
            {
                if (e.ElementType == QueryElementType.JoinedTable)
                {
                    var jt = (SelectQuery.JoinedTable)e;
                    if (jt.JoinType == SelectQuery.JoinType.Inner)
                    {
                        jt.IsWeak = false;
                    }
                }
            });

            var element = new SelectContext(buildInfo.Parent, elementSelector, sequence /*, key*/);
            var groupBy = new GroupByContext(buildInfo.Parent, sequenceExpr, groupingType, sequence, key, element);

            return(groupBy);
        }