public void CompileEmpty() { var expr = new RemoteGroupExpressionCompiler <DataItem>(null, null, null).Compile(CreateTargetParam <DataItem>()); Assert.Equal( "data" + ".GroupBy(obj => new AnonType())" + ".Select(g => new AnonType`1(I0 = g.Count()))", expr.ToString() ); }
void AddRemoteGrouping(bool suppressGroups, bool suppressTotals) { var compiler = new RemoteGroupExpressionCompiler( GetItemType(), Context.GuardNulls, Context.ExpandLinqSumType, Context.CreateAnonTypeNewTweaks(), suppressGroups ? null : Context.Group, suppressTotals ? null : Context.TotalSummary, suppressGroups ? null : Context.GroupSummary ); Expr = compiler.Compile(Expr); }
Expression BuildCore(Expression expr, bool paginate = false, bool isCountQuery = false, bool remoteGrouping = false) { var queryableType = typeof(Queryable); var genericTypeArguments = new[] { typeof(T) }; if (_loadOptions.HasFilter) { expr = Expression.Call(queryableType, "Where", genericTypeArguments, expr, Expression.Quote(new FilterExpressionCompiler <T>(_guardNulls).Compile(_loadOptions.Filter))); } if (!isCountQuery) { if (!remoteGrouping) { if (_loadOptions.HasAnySort) { expr = new SortExpressionCompiler <T>(_guardNulls).Compile(expr, _loadOptions.GetFullSort()); } if (_loadOptions.HasSelect) { expr = new SelectExpressionCompiler <T>(_guardNulls).Compile(expr, _loadOptions.Select); genericTypeArguments = expr.Type.GetGenericArguments(); } } else { expr = new RemoteGroupExpressionCompiler <T>(_loadOptions.Group, _loadOptions.TotalSummary, _loadOptions.GroupSummary).Compile(expr); } if (paginate) { if (_loadOptions.Skip > 0) { expr = Expression.Call(queryableType, "Skip", genericTypeArguments, expr, Expression.Constant(_loadOptions.Skip)); } if (_loadOptions.Take > 0) { expr = Expression.Call(queryableType, "Take", genericTypeArguments, expr, Expression.Constant(_loadOptions.Take)); } } } if (isCountQuery) { expr = Expression.Call(queryableType, "Count", genericTypeArguments, expr); } return(expr); }
Expression BuildCore(Expression expr, bool paginate = false, bool isCountQuery = false, bool remoteGrouping = false, IList filterOverride = null, IReadOnlyList <string> selectOverride = null) { var queryableType = typeof(Queryable); var genericTypeArguments = new[] { typeof(T) }; if (filterOverride != null || _context.HasFilter) { expr = Expression.Call(queryableType, "Where", genericTypeArguments, expr, Expression.Quote(new FilterExpressionCompiler <T>(_guardNulls, _context.UseStringToLower).Compile(filterOverride ?? _context.Filter))); } if (!isCountQuery) { if (!remoteGrouping) { if (_context.HasAnySort) { expr = new SortExpressionCompiler <T>(_guardNulls).Compile(expr, _context.GetFullSort()); } if (selectOverride != null || _context.HasAnySelect && _context.UseRemoteSelect) { expr = new SelectExpressionCompiler <T>(_guardNulls).Compile(expr, selectOverride ?? _context.FullSelect); genericTypeArguments = expr.Type.GetGenericArguments(); } } else { expr = new RemoteGroupExpressionCompiler <T>(_guardNulls, _anonTypeNewTweaks, _context.Group, _context.TotalSummary, _context.GroupSummary).Compile(expr); } if (paginate) { if (_context.Skip > 0) { expr = Expression.Call(queryableType, "Skip", genericTypeArguments, expr, Expression.Constant(_context.Skip)); } if (_context.Take > 0) { expr = Expression.Call(queryableType, "Take", genericTypeArguments, expr, Expression.Constant(_context.Take)); } } } if (isCountQuery) { expr = Expression.Call(queryableType, "Count", genericTypeArguments, expr); } return(expr); }
void Bug100Core <T>(params string[] memberNames) { var compiler = new RemoteGroupExpressionCompiler <T>( memberNames.Select(i => new GroupingInfo { Selector = i }).ToArray(), null, null ); Assert.Contains( "(" + String.Join(", ", memberNames.Select((i, index) => $"I{index} = obj.{i}")) + ")", compiler.Compile(CreateTargetParam <T>()).ToString() ); }
public void GroupInterval_NullableDate() { var compiler = new RemoteGroupExpressionCompiler <Nullable <DateTime> >( new[] { new GroupingInfo { Selector = "this", GroupInterval = "year" } }, null, null ); var expr = compiler.Compile(CreateTargetParam <Nullable <DateTime> >()).ToString(); Assert.Contains("I0 = IIF((obj == null), null, Convert(obj.Value.Year))", expr); }
public void GroupInterval_Numeric() { var compiler = new RemoteGroupExpressionCompiler <double>( new[] { new GroupingInfo { Selector = "this", GroupInterval = "123" } }, null, null ); var expr = compiler.Compile(CreateTargetParam <double>()).ToString(); Assert.Contains("I0 = (obj - (obj % Convert(123))", expr); }
Expression BuildCore(ParameterExpression param, bool paginate = false, bool isCountQuery = false, bool remoteGrouping = false) { var queryableType = typeof(Queryable); var genericTypeArguments = new[] { typeof(T) }; Expression body = param; if (_loadOptions.Filter != null) { body = Expression.Call(queryableType, "Where", genericTypeArguments, body, new FilterExpressionCompiler <T>(_guardNulls).Compile(_loadOptions.Filter)); } if (!isCountQuery) { if (!remoteGrouping) { if (_loadOptions.HasAnySort) { body = new SortExpressionCompiler <T>(_guardNulls).Compile(body, _loadOptions.GetFullSort()); } } else { body = new RemoteGroupExpressionCompiler <T>(_loadOptions.Group, _loadOptions.TotalSummary, _loadOptions.GroupSummary).Compile(body); } if (paginate) { if (_loadOptions.Skip > 0) { body = Expression.Call(queryableType, "Skip", genericTypeArguments, body, Expression.Constant(_loadOptions.Skip)); } if (_loadOptions.Take > 0) { body = Expression.Call(queryableType, "Take", genericTypeArguments, body, Expression.Constant(_loadOptions.Take)); } } } if (isCountQuery) { body = Expression.Call(queryableType, "Count", genericTypeArguments, body); } return(body); }
public void GroupInterval_Date() { var compiler = new RemoteGroupExpressionCompiler <DateTime>( new[] { new GroupingInfo { Selector = "this", GroupInterval = "year" }, new GroupingInfo { Selector = "this", GroupInterval = "quarter" }, new GroupingInfo { Selector = "this", GroupInterval = "month" }, new GroupingInfo { Selector = "this", GroupInterval = "day" }, new GroupingInfo { Selector = "this", GroupInterval = "dayOfWeek" }, new GroupingInfo { Selector = "this", GroupInterval = "hour" }, new GroupingInfo { Selector = "this", GroupInterval = "minute" }, new GroupingInfo { Selector = "this", GroupInterval = "second" } }, null, null ); var expr = compiler.Compile(CreateTargetParam <DateTime>()).ToString(); Assert.Contains("I0 = obj.Year", expr); Assert.Contains("I1 = ((obj.Month + 2) / 3)", expr); Assert.Contains("I2 = obj.Month", expr); Assert.Contains("I3 = obj.Day", expr); Assert.Contains("I4 = Convert(obj.DayOfWeek)", expr); Assert.Contains("I5 = obj.Hour", expr); Assert.Contains("I6 = obj.Minute", expr); Assert.Contains("I7 = obj.Second", expr); }
public void GetSumType_ExpandFalse() { Type GetSumType <T>() => RemoteGroupExpressionCompiler.GetSumType(typeof(T), false); // Validation: check lambda type in new T[0].Sum(i => i) Assert.Equal(typeof(int), GetSumType <sbyte>()); Assert.Equal(typeof(int), GetSumType <byte>()); Assert.Equal(typeof(int), GetSumType <short>()); Assert.Equal(typeof(int), GetSumType <ushort>()); Assert.Equal(typeof(int), GetSumType <int>()); Assert.Equal(typeof(long), GetSumType <uint>()); Assert.Equal(typeof(long), GetSumType <long>()); Assert.Equal(typeof(decimal), GetSumType <ulong>()); Assert.Equal(typeof(float), GetSumType <float>()); Assert.Equal(typeof(double), GetSumType <double>()); Assert.Equal(typeof(decimal), GetSumType <decimal>()); }
public void GetSumType_ExpandTrue() { Type GetSumType <T>() => RemoteGroupExpressionCompiler.GetSumType(typeof(T), true); // Don't convert integer types to decimal because SQL decimals have variable precision // Except for UInt64 for which there is no better choice Assert.Equal(typeof(long), GetSumType <sbyte>()); Assert.Equal(typeof(long), GetSumType <byte>()); Assert.Equal(typeof(long), GetSumType <short>()); Assert.Equal(typeof(long), GetSumType <ushort>()); Assert.Equal(typeof(long), GetSumType <int>()); Assert.Equal(typeof(long), GetSumType <uint>()); Assert.Equal(typeof(long), GetSumType <long>()); Assert.Equal(typeof(decimal), GetSumType <ulong>()); Assert.Equal(typeof(double), GetSumType <float>()); Assert.Equal(typeof(double), GetSumType <double>()); Assert.Equal(typeof(decimal), GetSumType <decimal>()); }
public void Compile() { var compiler = new RemoteGroupExpressionCompiler <DataItem>( new[] { new GroupingInfo { Selector = "G1" }, new GroupingInfo { Selector = "G2", Desc = true } }, new[] { new SummaryInfo { Selector = "Value", SummaryType = "sum" }, new SummaryInfo { Selector = "Value", SummaryType = "min" }, new SummaryInfo { Selector = "Value", SummaryType = "max" }, new SummaryInfo { Selector = "Value", SummaryType = "avg" }, new SummaryInfo { SummaryType = "count" } }, new[] { new SummaryInfo { SummaryType = "count" }, new SummaryInfo { Selector = "Nullable", SummaryType = "avg" }, new SummaryInfo { Selector = "Nullable", SummaryType = "max" }, new SummaryInfo { Selector = "Nullable", SummaryType = "min" }, new SummaryInfo { Selector = "Nullable", SummaryType = "sum" } } ); var expr = compiler.Compile(CreateTargetParam <DataItem>()); Assert.Equal( "data" + ".GroupBy(obj => new AnonType`2(I0 = obj.G1, I1 = obj.G2))" + ".OrderBy(g => g.Key.I0)" + ".ThenByDescending(g => g.Key.I1)" + ".Select(g => new AnonType`16(" // count + "I0 = g.Count(), " // keys + "I1 = g.Key.I0, " + "I2 = g.Key.I1, " // total summary + "I3 = g.Sum(obj => obj.Value), " + "I4 = g.Min(obj => obj.Value), " + "I5 = g.Max(obj => obj.Value), " + "I6 = g.Sum(obj => obj.Value), " // avg sum + "I7 = g.Count(), " // avg count // (count skipped) // group summary // (count skipped) + "I8 = g.Sum(obj => obj.Nullable), " // avg sum + "I9 = g.Select(obj => IIF((obj.Nullable != null), 1, 0)).Sum(), " // avg count + "I10 = g.Max(obj => obj.Nullable), " + "I11 = g.Min(obj => obj.Nullable), " + "I12 = g.Sum(obj => obj.Nullable)" + "))", expr.ToString() ); }
public void GroupInterval_Date() { string Compile <T>(string selector, bool guardNulls) { var compiler = new RemoteGroupExpressionCompiler <T>( guardNulls, new[] { new GroupingInfo { Selector = selector, GroupInterval = "year" }, new GroupingInfo { Selector = selector, GroupInterval = "quarter" }, new GroupingInfo { Selector = selector, GroupInterval = "month" }, new GroupingInfo { Selector = selector, GroupInterval = "day" }, new GroupingInfo { Selector = selector, GroupInterval = "dayOfWeek" }, new GroupingInfo { Selector = selector, GroupInterval = "hour" }, new GroupingInfo { Selector = selector, GroupInterval = "minute" }, new GroupingInfo { Selector = selector, GroupInterval = "second" } }, null, null ); return(compiler.Compile(CreateTargetParam <T>()).ToString()); } { var expr = Compile <DateTime>("this", false); Assert.Contains("I0 = obj.Year", expr); Assert.Contains("I1 = ((obj.Month + 2) / 3)", expr); Assert.Contains("I2 = obj.Month", expr); Assert.Contains("I3 = obj.Day", expr); Assert.Contains("I4 = " + Compat.ExpectedConvert("obj.DayOfWeek", "Int32"), expr); Assert.Contains("I5 = obj.Hour", expr); Assert.Contains("I6 = obj.Minute", expr); Assert.Contains("I7 = obj.Second", expr); } { var expr = Compile <DateTime?>("this", false); string Wrap(string coreSelector) { return(Compat.ExpectedConvert(coreSelector, "Nullable`1")); } Assert.Contains("I0 = " + Wrap("obj.Value.Year"), expr); Assert.Contains("I1 = " + Wrap("((obj.Value.Month + 2) / 3)"), expr); Assert.Contains("I2 = " + Wrap("obj.Value.Month"), expr); Assert.Contains("I3 = " + Wrap("obj.Value.Day"), expr); Assert.Contains("I4 = " + Wrap("obj.Value.DayOfWeek"), expr); Assert.Contains("I5 = " + Wrap("obj.Value.Hour"), expr); Assert.Contains("I6 = " + Wrap("obj.Value.Minute"), expr); Assert.Contains("I7 = " + Wrap("obj.Value.Second"), expr); } { var expr = Compile <Tuple <DateTime?> >("Item1", true); string Wrap(string coreSelector) { return($"IIF(((obj == null) OrElse (obj.Item1 == null)), null, {Compat.ExpectedConvert(coreSelector, "Nullable`1")})"); } Assert.Contains("I0 = " + Wrap("obj.Item1.Value.Year"), expr); Assert.Contains("I1 = " + Wrap("((obj.Item1.Value.Month + 2) / 3)"), expr); Assert.Contains("I2 = " + Wrap("obj.Item1.Value.Month"), expr); Assert.Contains("I3 = " + Wrap("obj.Item1.Value.Day"), expr); Assert.Contains("I4 = " + Wrap("obj.Item1.Value.DayOfWeek"), expr); Assert.Contains("I5 = " + Wrap("obj.Item1.Value.Hour"), expr); Assert.Contains("I6 = " + Wrap("obj.Item1.Value.Minute"), expr); Assert.Contains("I7 = " + Wrap("obj.Item1.Value.Second"), expr); } }
public void Compile() { var compiler = new RemoteGroupExpressionCompiler <DataItem>( new[] { new GroupingInfo { Selector = "G1" }, new GroupingInfo { Selector = "G2", Desc = true } }, new[] { new SummaryInfo { Selector = "Value", SummaryType = "sum" }, new SummaryInfo { Selector = "Value", SummaryType = "min" }, new SummaryInfo { Selector = "Value", SummaryType = "max" }, new SummaryInfo { Selector = "Value", SummaryType = "avg" }, new SummaryInfo { SummaryType = "count" } }, new[] { new SummaryInfo { SummaryType = "count" }, new SummaryInfo { Selector = "Value", SummaryType = "avg" }, new SummaryInfo { Selector = "Value", SummaryType = "max" }, new SummaryInfo { Selector = "Value", SummaryType = "min" }, new SummaryInfo { Selector = "Value", SummaryType = "sum" } } ); var expr = compiler.Compile(CreateTargetParam <DataItem>()); Assert.Equal( "data" + ".GroupBy(obj => new RemoteGroupKey`8(K0 = obj.G1, K1 = obj.G2))" + ".OrderBy(g => g.Key.K0)" + ".ThenByDescending(g => g.Key.K1)" + ".Select(g => new RemoteGroup`24() {" + "K0 = g.Key.K0, " + "K1 = g.Key.K1, " + "Count = g.Count(), " + "G1 = g.Sum(obj => obj.Value), " + "G2 = g.Max(obj => obj.Value), " + "G3 = g.Min(obj => obj.Value), " + "G4 = g.Sum(obj => obj.Value), " + "T0 = g.Sum(obj => obj.Value), " + "T1 = g.Min(obj => obj.Value), " + "T2 = g.Max(obj => obj.Value), " + "T3 = g.Sum(obj => obj.Value)" + "})", expr.ToString() ); }