public static AggregationExpression Translate(TranslationContext context, MethodCallExpression expression) { var method = expression.Method; var arguments = expression.Arguments; if (method.Is(EnumerableMethod.Zip)) { var firstExpression = arguments[0]; var firstTranslation = ExpressionToAggregationExpressionTranslator.TranslateEnumerable(context, firstExpression); var secondExpression = arguments[1]; var secondTranslation = ExpressionToAggregationExpressionTranslator.TranslateEnumerable(context, secondExpression); var resultSelectorLambda = (LambdaExpression)arguments[2]; var resultSelectorParameters = resultSelectorLambda.Parameters; var resultSelectorParameter1 = resultSelectorParameters[0]; var resultSelectorParameter2 = resultSelectorParameters[1]; var resultSelectorSymbol1 = context.CreateSymbol(resultSelectorParameter1, BsonSerializer.LookupSerializer(resultSelectorParameter1.Type)); var resultSelectorSymbol2 = context.CreateSymbol(resultSelectorParameter2, BsonSerializer.LookupSerializer(resultSelectorParameter2.Type)); var resultSelectorContext = context.WithSymbols(resultSelectorSymbol1, resultSelectorSymbol2); var resultSelectorTranslation = ExpressionToAggregationExpressionTranslator.Translate(resultSelectorContext, resultSelectorLambda.Body); var @as = AstExpression.Var("pair"); var ast = AstExpression.Map( input: AstExpression.Zip(new[] { firstTranslation.Ast, secondTranslation.Ast }), @as: @as, @in: AstExpression.Let( AstExpression.VarBinding(resultSelectorSymbol1.Var, AstExpression.ArrayElemAt(@as, 0)), AstExpression.VarBinding(resultSelectorSymbol2.Var, AstExpression.ArrayElemAt(@as, 1)), @in: resultSelectorTranslation.Ast)); var serializer = IEnumerableSerializer.Create(resultSelectorTranslation.Serializer); return(new AggregationExpression(expression, ast, serializer)); } throw new ExpressionNotSupportedException(expression); }
public static AggregationExpression Translate(TranslationContext context, MethodCallExpression expression) { var method = expression.Method; var arguments = expression.Arguments; if (method.Is(EnumerableMethod.All)) { var sourceExpression = arguments[0]; var sourceTranslation = ExpressionToAggregationExpressionTranslator.TranslateEnumerable(context, sourceExpression); var predicateLambda = (LambdaExpression)arguments[1]; var predicateParameter = predicateLambda.Parameters[0]; var predicateParameterSerializer = ArraySerializerHelper.GetItemSerializer(sourceTranslation.Serializer); var predicateSymbol = context.CreateSymbol(predicateParameter, predicateParameterSerializer); var predicateContext = context.WithSymbol(predicateSymbol); var predicateTranslation = ExpressionToAggregationExpressionTranslator.Translate(predicateContext, predicateLambda.Body); var ast = AstExpression.AllElementsTrue( AstExpression.Map( input: sourceTranslation.Ast, @as: predicateSymbol.Var, @in: predicateTranslation.Ast)); return(new AggregationExpression(expression, ast, new BooleanSerializer())); } throw new ExpressionNotSupportedException(expression); }
public static AggregationExpression Translate(TranslationContext context, MethodCallExpression expression) { var method = expression.Method; var arguments = expression.Arguments; if (method.Is(EnumerableMethod.Select)) { var sourceExpression = arguments[0]; var sourceTranslation = ExpressionToAggregationExpressionTranslator.TranslateEnumerable(context, sourceExpression); var selectorLambda = (LambdaExpression)arguments[1]; var selectorParameter = selectorLambda.Parameters[0]; var selectorParameterSerializer = ArraySerializerHelper.GetItemSerializer(sourceTranslation.Serializer); var selectorParameterSymbol = context.CreateSymbol(selectorParameter, selectorParameterSerializer); var selectorContext = context.WithSymbol(selectorParameterSymbol); var translatedSelector = ExpressionToAggregationExpressionTranslator.Translate(selectorContext, selectorLambda.Body); var ast = AstExpression.Map( sourceTranslation.Ast, selectorParameterSymbol.Var, translatedSelector.Ast); var serializer = IEnumerableSerializer.Create(translatedSelector.Serializer); return(new AggregationExpression(expression, ast, serializer)); } throw new ExpressionNotSupportedException(expression); }
public static AggregationExpression Translate(TranslationContext context, MethodCallExpression expression) { var method = expression.Method; var arguments = expression.Arguments; if (method.IsOneOf(EnumerableMethod.First, EnumerableMethod.FirstWithPredicate, EnumerableMethod.Last, EnumerableMethod.LastWithPredicate)) { var sourceExpression = arguments[0]; var sourceTranslation = ExpressionToAggregationExpressionTranslator.TranslateEnumerable(context, sourceExpression); var array = sourceTranslation.Ast; var itemSerializer = ArraySerializerHelper.GetItemSerializer(sourceTranslation.Serializer); if (method.IsOneOf(EnumerableMethod.FirstWithPredicate, EnumerableMethod.LastWithPredicate)) { var predicateLambda = (LambdaExpression)arguments[1]; var predicateTranslation = ExpressionToAggregationExpressionTranslator.TranslateLambdaBody(context, predicateLambda, itemSerializer, asRoot: false); var predicateParameter = predicateLambda.Parameters[0]; array = AstExpression.Filter( input: array, cond: predicateTranslation.Ast, @as: predicateParameter.Name); } var ast = method.Name == "First" ? AstExpression.First(array) : AstExpression.Last(array); return(new AggregationExpression(expression, ast, itemSerializer)); } if (WindowMethodToAggregationExpressionTranslator.CanTranslate(expression)) { return(WindowMethodToAggregationExpressionTranslator.Translate(context, expression)); } throw new ExpressionNotSupportedException(expression); }
private static AggregationExpression TranslateEnumerableContains(TranslationContext context, Expression expression, Expression sourceExpression, Expression valueExpression) { var sourceTranslation = ExpressionToAggregationExpressionTranslator.TranslateEnumerable(context, sourceExpression); var valueTranslation = ExpressionToAggregationExpressionTranslator.Translate(context, valueExpression); var ast = AstExpression.In(valueTranslation.Ast, sourceTranslation.Ast); return(new AggregationExpression(expression, ast, new BooleanSerializer())); }
public static AggregationExpression Translate(TranslationContext context, MethodCallExpression expression) { var method = expression.Method; var arguments = expression.Arguments; if (method.IsOneOf(__averageMethods)) { var sourceExpression = arguments[0]; var sourceTranslation = ExpressionToAggregationExpressionTranslator.TranslateEnumerable(context, sourceExpression); AstExpression ast; if (method.IsOneOf(__averageWithSelectorMethods)) { var selectorLambda = (LambdaExpression)arguments[1]; var selectorParameter = selectorLambda.Parameters[0]; var sourceItemSerializer = ArraySerializerHelper.GetItemSerializer(sourceTranslation.Serializer); var selectorSymbol = context.CreateSymbol(selectorParameter, sourceItemSerializer); var selectorContext = context.WithSymbol(selectorSymbol); var selectorTranslation = ExpressionToAggregationExpressionTranslator.Translate(selectorContext, selectorLambda.Body); ast = AstExpression.Avg( AstExpression.Map( input: sourceTranslation.Ast, @as: selectorSymbol.Var, @in: selectorTranslation.Ast)); } else { ast = AstExpression.Avg(sourceTranslation.Ast); } IBsonSerializer serializer = expression.Type switch { Type t when t == typeof(int) => new Int32Serializer(), Type t when t == typeof(long) => new Int64Serializer(), Type t when t == typeof(float) => new SingleSerializer(), Type t when t == typeof(double) => new DoubleSerializer(), Type t when t == typeof(decimal) => new DecimalSerializer(), Type { IsConstructedGenericType : true } t when t.GetGenericTypeDefinition() == typeof(Nullable <>) => (IBsonSerializer)Activator.CreateInstance(typeof(NullableSerializer <>).MakeGenericType(t.GenericTypeArguments[0])), _ => throw new ExpressionNotSupportedException(expression) }; return(new AggregationExpression(expression, ast, serializer)); } if (SetWindowFieldsMethodToAggregationExpressionTranslator.CanTranslate(expression)) { return(SetWindowFieldsMethodToAggregationExpressionTranslator.Translate(context, expression)); } throw new ExpressionNotSupportedException(expression); } }
public static AggregationExpression Translate(TranslationContext context, MethodCallExpression expression) { var method = expression.Method; var arguments = expression.Arguments; if (method.IsOneOf(__countMethods)) { var sourceExpression = arguments[0]; var sourceTranslation = ExpressionToAggregationExpressionTranslator.TranslateEnumerable(context, sourceExpression); AstExpression ast; if (method.IsOneOf(__countWithPredicateMethods)) { if (sourceExpression.Type == typeof(string)) { throw new ExpressionNotSupportedException(expression); } var predicateLambda = (LambdaExpression)arguments[1]; var sourceItemSerializer = ArraySerializerHelper.GetItemSerializer(sourceTranslation.Serializer); var predicateTranslation = ExpressionToAggregationExpressionTranslator.TranslateLambdaBody(context, predicateLambda, sourceItemSerializer, asRoot: false); var filteredSourceAst = AstExpression.Filter( input: sourceTranslation.Ast, cond: predicateTranslation.Ast, @as: predicateLambda.Parameters[0].Name); ast = AstExpression.Size(filteredSourceAst); } else { if (sourceExpression.Type == typeof(string)) { ast = AstExpression.StrLenCP(sourceTranslation.Ast); } else { ast = AstExpression.Size(sourceTranslation.Ast); } } var serializer = GetSerializer(expression.Type); return(new AggregationExpression(expression, ast, serializer)); } if (WindowMethodToAggregationExpressionTranslator.CanTranslate(expression)) { return(WindowMethodToAggregationExpressionTranslator.Translate(context, expression)); } throw new ExpressionNotSupportedException(expression); }
public static AggregationExpression Translate(TranslationContext context, MethodCallExpression expression) { var method = expression.Method; var arguments = expression.Arguments; if (method.Is(EnumerableMethod.Distinct)) { var sourceExpression = arguments[0]; var sourceTranslation = ExpressionToAggregationExpressionTranslator.TranslateEnumerable(context, sourceExpression); var ast = AstExpression.SetIntersection(sourceTranslation.Ast); return(new AggregationExpression(expression, ast, sourceTranslation.Serializer)); } throw new ExpressionNotSupportedException(expression); }
public static AggregationExpression Translate(TranslationContext context, MethodCallExpression expression) { var method = expression.Method; var arguments = expression.Arguments; if (method.Is(EnumerableMethod.Reverse)) { var sourceExpression = arguments[0]; var sourceTranslation = ExpressionToAggregationExpressionTranslator.TranslateEnumerable(context, sourceExpression); var ast = AstExpression.ReverseArray(sourceTranslation.Ast); var itemSerializer = ArraySerializerHelper.GetItemSerializer(sourceTranslation.Serializer); var serializer = IEnumerableSerializer.Create(itemSerializer); return(new AggregationExpression(expression, ast, serializer)); } throw new ExpressionNotSupportedException(expression); }
public static AggregationExpression Translate(TranslationContext context, MethodCallExpression expression) { var method = expression.Method; var arguments = expression.Arguments; if (method.Is(EnumerableMethod.ToArray)) { var sourceExpression = arguments[0]; var sourceTranslation = ExpressionToAggregationExpressionTranslator.TranslateEnumerable(context, sourceExpression); var arrayItemSerializer = ArraySerializerHelper.GetItemSerializer(sourceTranslation.Serializer); var arrayItemType = arrayItemSerializer.ValueType; var arraySerializerType = typeof(ArraySerializer <>).MakeGenericType(arrayItemType); var arraySerializer = (IBsonSerializer)Activator.CreateInstance(arraySerializerType, arrayItemSerializer); return(new AggregationExpression(expression, sourceTranslation.Ast, arraySerializer)); } throw new ExpressionNotSupportedException(expression); }
public static AggregationExpression Translate(TranslationContext context, MethodCallExpression expression) { var method = expression.Method; var arguments = expression.Arguments; if (method.IsOneOf(__sumMethods)) { var sourceExpression = arguments[0]; var sourceTranslation = ExpressionToAggregationExpressionTranslator.TranslateEnumerable(context, sourceExpression); var sourceItemSerializer = ArraySerializerHelper.GetItemSerializer(sourceTranslation.Serializer); AstExpression ast; IBsonSerializer serializer; if (arguments.Count == 1) { ast = AstExpression.Sum(sourceTranslation.Ast); serializer = sourceItemSerializer; } else { var selectorLambda = (LambdaExpression)arguments[1]; var selectorParameter = selectorLambda.Parameters[0]; var selectorSymbol = context.CreateSymbol(selectorParameter, sourceItemSerializer); var selectorContext = context.WithSymbol(selectorSymbol); var selectorTranslation = ExpressionToAggregationExpressionTranslator.Translate(selectorContext, selectorLambda.Body); ast = AstExpression.Sum( AstExpression.Map( input: sourceTranslation.Ast, @as: selectorSymbol.Var, @in: selectorTranslation.Ast)); serializer = selectorTranslation.Serializer; } return(new AggregationExpression(expression, ast, serializer)); } if (SetWindowFieldsMethodToAggregationExpressionTranslator.CanTranslate(expression)) { return(SetWindowFieldsMethodToAggregationExpressionTranslator.Translate(context, expression)); } throw new ExpressionNotSupportedException(expression); }
public static AggregationExpression Translate(TranslationContext context, MethodCallExpression expression) { var method = expression.Method; var arguments = expression.Arguments; if (method.DeclaringType == typeof(Enumerable) && (method.Name == "Max" || method.Name == "Min")) { var sourceExpression = arguments[0]; var sourceTranslation = ExpressionToAggregationExpressionTranslator.TranslateEnumerable(context, sourceExpression); AstExpression ast; IBsonSerializer serializer; if (arguments.Count == 1) { var array = sourceTranslation.Ast; ast = method.Name == "Max" ? AstExpression.Max(array) : AstExpression.Min(array); serializer = ArraySerializerHelper.GetItemSerializer(sourceTranslation.Serializer); } else { var selectorLambda = (LambdaExpression)arguments[1]; var selectorParameter = selectorLambda.Parameters[0]; var selectorParameterSerializer = ArraySerializerHelper.GetItemSerializer(sourceTranslation.Serializer); var selectorParameterSymbol = context.CreateSymbol(selectorParameter, selectorParameterSerializer); var selectorContext = context.WithSymbol(selectorParameterSymbol); var selectorTranslation = ExpressionToAggregationExpressionTranslator.Translate(selectorContext, selectorLambda.Body); var mappedArray = AstExpression.Map( input: sourceTranslation.Ast, @as: selectorParameterSymbol.Var, @in: selectorTranslation.Ast); ast = method.Name == "Max" ? AstExpression.Max(mappedArray) : AstExpression.Min(mappedArray); serializer = selectorTranslation.Serializer; } return(new AggregationExpression(expression, ast, serializer)); } if (SetWindowFieldsMethodToAggregationExpressionTranslator.CanTranslate(expression)) { return(SetWindowFieldsMethodToAggregationExpressionTranslator.Translate(context, expression)); } throw new ExpressionNotSupportedException(expression); }
public static AggregationExpression Translate(TranslationContext context, MethodCallExpression expression) { var method = expression.Method; var arguments = expression.Arguments; if (IsStandardDeviationMethod(method, out var stddevOperator)) { if (arguments.Count == 1 || arguments.Count == 2) { var sourceExpression = arguments[0]; var sourceTranslation = ExpressionToAggregationExpressionTranslator.TranslateEnumerable(context, sourceExpression); if (arguments.Count == 2) { var selectorLambda = (LambdaExpression)arguments[1]; var selectorParameter = selectorLambda.Parameters[0]; var selectorParameterSerializer = ArraySerializerHelper.GetItemSerializer(sourceTranslation.Serializer); var selectorParameterSymbol = context.CreateSymbol(selectorParameter, selectorParameterSerializer); var selectorContext = context.WithSymbol(selectorParameterSymbol); var selectorTranslation = ExpressionToAggregationExpressionTranslator.Translate(selectorContext, selectorLambda.Body); var selectorAst = AstExpression.Map( input: sourceTranslation.Ast, @as: selectorParameterSymbol.Var, @in: selectorTranslation.Ast); var selectorResultSerializer = BsonSerializer.LookupSerializer(selectorLambda.ReturnType); sourceTranslation = new AggregationExpression(selectorLambda, selectorAst, selectorResultSerializer); } var ast = AstExpression.StdDev(stddevOperator, sourceTranslation.Ast); var serializer = BsonSerializer.LookupSerializer(expression.Type); return(new AggregationExpression(expression, ast, serializer)); } } if (SetWindowFieldsMethodToAggregationExpressionTranslator.CanTranslate(expression)) { return(SetWindowFieldsMethodToAggregationExpressionTranslator.Translate(context, expression)); } throw new ExpressionNotSupportedException(expression); }
public static AggregationExpression Translate(TranslationContext context, MethodCallExpression expression) { var method = expression.Method; var arguments = expression.Arguments; if (method.IsOneOf(EnumerableMethod.Where, MongoEnumerableMethod.WhereWithLimit)) { var sourceExpression = arguments[0]; var sourceTranslation = ExpressionToAggregationExpressionTranslator.TranslateEnumerable(context, sourceExpression); var itemSerializer = ArraySerializerHelper.GetItemSerializer(sourceTranslation.Serializer); var predicateLambda = (LambdaExpression)arguments[1]; var predicateParameter = predicateLambda.Parameters[0]; var predicateSymbol = context.CreateSymbol(predicateParameter, itemSerializer); var predicateContext = context.WithSymbol(predicateSymbol); var predicateTranslation = ExpressionToAggregationExpressionTranslator.Translate(predicateContext, predicateLambda.Body); AggregationExpression limitTranslation = null; if (method.Is(MongoEnumerableMethod.WhereWithLimit)) { var limitExpression = arguments[2]; limitTranslation = ExpressionToAggregationExpressionTranslator.Translate(context, limitExpression); } var ast = AstExpression.Filter( sourceTranslation.Ast, predicateTranslation.Ast, predicateParameter.Name, limitTranslation?.Ast); var enumerableSerializer = IEnumerableSerializer.Create(itemSerializer); return(new AggregationExpression(expression, ast, enumerableSerializer)); } throw new ExpressionNotSupportedException(expression); }
public static AggregationExpression Translate(TranslationContext context, MethodCallExpression expression) { var method = expression.Method; var arguments = expression.Arguments; if (method.Is(EnumerableMethod.Take)) { var sourceExpression = arguments[0]; var countExpression = arguments[1]; Expression skipExpression = null; if (sourceExpression is MethodCallExpression sourceSkipExpression && sourceSkipExpression.Method.Is(EnumerableMethod.Skip)) { sourceExpression = sourceSkipExpression.Arguments[0]; skipExpression = sourceSkipExpression.Arguments[1]; } var sourceTranslation = ExpressionToAggregationExpressionTranslator.TranslateEnumerable(context, sourceExpression); var countTranslation = ExpressionToAggregationExpressionTranslator.Translate(context, countExpression); AstExpression ast; if (skipExpression == null) { ast = AstExpression.Slice(sourceTranslation.Ast, countTranslation.Ast); } else { var skipTranslation = ExpressionToAggregationExpressionTranslator.Translate(context, skipExpression); ast = AstExpression.Slice(sourceTranslation.Ast, skipTranslation.Ast, countTranslation.Ast); } var itemSerializer = ArraySerializerHelper.GetItemSerializer(sourceTranslation.Serializer); var serializer = IEnumerableSerializer.Create(itemSerializer); return(new AggregationExpression(expression, ast, serializer)); } throw new ExpressionNotSupportedException(expression); }
public static AggregationExpression Translate(TranslationContext context, MethodCallExpression expression) { var method = expression.Method; var arguments = expression.Arguments; if (method.IsOneOf(EnumerableMethod.DefaultIfEmpty, EnumerableMethod.DefaultIfEmptyWithDefaultValue)) { var sourceExpression = arguments[0]; var sourceTranslation = ExpressionToAggregationExpressionTranslator.TranslateEnumerable(context, sourceExpression); var sourceVar = AstExpression.Var("source"); var sourceVarBinding = AstExpression.VarBinding(sourceVar, sourceTranslation.Ast); AstExpression defaultValueAst; if (method.Is(EnumerableMethod.DefaultIfEmpty)) { var sourceItemSerializer = ArraySerializerHelper.GetItemSerializer(sourceTranslation.Serializer); var defaultValue = Activator.CreateInstance(sourceItemSerializer.ValueType); var serializedDefaultValue = SerializationHelper.SerializeValue(sourceItemSerializer, defaultValue); defaultValueAst = AstExpression.Constant(new BsonArray { serializedDefaultValue }); } else { var defaultValueExpression = arguments[1]; var defaultValueTranslation = ExpressionToAggregationExpressionTranslator.Translate(context, defaultValueExpression); defaultValueAst = AstExpression.ComputedArray(new[] { defaultValueTranslation.Ast }); } var ast = AstExpression.Let( sourceVarBinding, AstExpression.Cond( AstExpression.Eq(AstExpression.Size(sourceVar), 0), defaultValueAst, sourceVar)); return new AggregationExpression(expression, ast, sourceTranslation.Serializer); } throw new ExpressionNotSupportedException(expression); }
public static AggregationExpression Translate(TranslationContext context, MethodCallExpression expression) { var method = expression.Method; var arguments = expression.Arguments; if (method.IsOneOf(__setWindowFieldsMethods)) { var partitionExpression = arguments[0]; var partitionTranslation = ExpressionToAggregationExpressionTranslator.TranslateEnumerable(context, partitionExpression); var partitionSerializer = (ISetWindowFieldsPartitionSerializer)partitionTranslation.Serializer; var inputSerializer = partitionSerializer.InputSerializer; var @operator = ToOperator(method); var operatorArgs = new List <AstExpression>(); IBsonSerializer defaultValueSerializer = null; AstSetWindowFieldsWindow astWindow = null; for (var n = 1; n < arguments.Count; n++) { var argument = arguments[n]; if (argument is LambdaExpression selectorLambda) { var selectorParameter = selectorLambda.Parameters[0]; var selectorSymbol = context.CreateSymbol(selectorParameter, inputSerializer, isCurrent: true); var selectorContext = context.WithSymbol(selectorSymbol); var selectorTranslation = ExpressionToAggregationExpressionTranslator.Translate(selectorContext, selectorLambda.Body); operatorArgs.Add(selectorTranslation.Ast); if (method.Is(SetWindowFieldsMethod.ShiftWithDefaultValue) && n == 1) { defaultValueSerializer = selectorTranslation.Serializer; } continue; } if (argument is ConstantExpression constantExpression) { var value = constantExpression.GetConstantValue <object>(expression); if (method.IsOneOf(SetWindowFieldsMethod.Shift, SetWindowFieldsMethod.ShiftWithDefaultValue) && n == 2) { var by = (int)value; operatorArgs.Add(by); continue; } if (method.Is(SetWindowFieldsMethod.ShiftWithDefaultValue) && n == 3) { var defaultValue = value; var serializedDefaultValue = SerializationHelper.SerializeValue(defaultValueSerializer, defaultValue); operatorArgs.Add(serializedDefaultValue); continue; } if (value is WindowTimeUnit unit) { var renderedUnit = unit.Render(); operatorArgs.Add(renderedUnit); continue; } if (value is ExponentialMovingAverageAlphaWeighting alphaWeighting) { @operator = AstSetWindowFieldsOperator.ExpMovingAvgWithAlphaWeighting; operatorArgs.Add(alphaWeighting.Alpha); continue; } if (value is ExponentialMovingAveragePositionalWeighting positionalWeighting) { @operator = AstSetWindowFieldsOperator.ExpMovingAvgWithPositionalWeighting; operatorArgs.Add(positionalWeighting.N); continue; } if (HasWindowParameter(method) && n == arguments.Count - 1) { if (value != null) { var window = (SetWindowFieldsWindow)value; var sortBy = context.Data?.GetValueOrDefault <object>("SortBy", null); var serializerRegistry = context.Data?.GetValueOrDefault <BsonSerializerRegistry>("SerializerRegistry", null); astWindow = ToAstWindow(window, sortBy, inputSerializer, serializerRegistry); } continue; } } throw new ExpressionNotSupportedException(argument, expression); } if (operatorArgs.Count == 0) { operatorArgs.Add(new BsonDocument()); } var ast = AstExpression.SetWindowFieldsWindowExpression( @operator, operatorArgs, astWindow); var serializer = BsonSerializer.LookupSerializer(method.ReturnType); // TODO: use correct serializer return(new AggregationExpression(expression, ast, serializer)); } throw new ExpressionNotSupportedException(expression); }
public static AggregationExpression Translate(TranslationContext context, MethodCallExpression expression) { var method = expression.Method; var arguments = expression.Arguments; if (method.IsOneOf(__aggregateMethods)) { var sourceExpression = arguments[0]; var sourceTranslation = ExpressionToAggregationExpressionTranslator.TranslateEnumerable(context, sourceExpression); var itemSerializer = ArraySerializerHelper.GetItemSerializer(sourceTranslation.Serializer); if (method.Is(EnumerableMethod.AggregateWithFunc)) { var funcLambda = (LambdaExpression)arguments[1]; var funcParameters = funcLambda.Parameters; var accumulatorParameter = funcParameters[0]; var accumulatorSymbol = context.CreateSymbolWithVarName(accumulatorParameter, varName: "value", itemSerializer); // note: MQL uses $$value for the accumulator var itemParameter = funcParameters[1]; var itemSymbol = context.CreateSymbolWithVarName(itemParameter, varName: "this", itemSerializer); // note: MQL uses $$this for the item being processed var funcContext = context.WithSymbols(accumulatorSymbol, itemSymbol); var funcTranslation = ExpressionToAggregationExpressionTranslator.Translate(funcContext, funcLambda.Body); var sourceVar = AstExpression.Var("source"); var ast = AstExpression.Let( var: AstExpression.VarBinding(sourceVar, sourceTranslation.Ast), @in: AstExpression.Cond( @if: AstExpression.Lte(AstExpression.Size(sourceVar), 1), @then: AstExpression.ArrayElemAt(sourceVar, 0), @else: AstExpression.Reduce( input: AstExpression.Slice(sourceVar, 1, int.MaxValue), initialValue: AstExpression.ArrayElemAt(sourceVar, 0), @in: funcTranslation.Ast))); return(new AggregationExpression(expression, ast, itemSerializer)); } else if (method.IsOneOf(EnumerableMethod.AggregateWithSeedAndFunc, EnumerableMethod.AggregateWithSeedFuncAndResultSelector)) { var seedExpression = arguments[1]; var seedTranslation = ExpressionToAggregationExpressionTranslator.Translate(context, seedExpression); var funcLambda = (LambdaExpression)arguments[2]; var funcParameters = funcLambda.Parameters; var accumulatorParameter = funcParameters[0]; var accumulatorSerializer = context.KnownSerializersRegistry.GetSerializer(accumulatorParameter); var accumulatorSymbol = context.CreateSymbolWithVarName(accumulatorParameter, varName: "value", accumulatorSerializer); // note: MQL uses $$value for the accumulator var itemParameter = funcParameters[1]; var itemSymbol = context.CreateSymbolWithVarName(itemParameter, varName: "this", itemSerializer); // note: MQL uses $$this for the item being processed var funcContext = context.WithSymbols(accumulatorSymbol, itemSymbol); var funcTranslation = ExpressionToAggregationExpressionTranslator.Translate(funcContext, funcLambda.Body); var ast = AstExpression.Reduce( input: sourceTranslation.Ast, initialValue: seedTranslation.Ast, @in: funcTranslation.Ast); var serializer = accumulatorSerializer; if (method.Is(EnumerableMethod.AggregateWithSeedFuncAndResultSelector)) { var resultSelectorLambda = (LambdaExpression)arguments[3]; var resultSelectorParameter = resultSelectorLambda.Parameters[0]; var resultSelectorParameterSerializer = context.KnownSerializersRegistry.GetSerializer(resultSelectorParameter); var resultSelectorSymbol = context.CreateSymbol(resultSelectorParameter, resultSelectorParameterSerializer); var resultSelectorContext = context.WithSymbol(resultSelectorSymbol); var resultSelectorTranslation = ExpressionToAggregationExpressionTranslator.Translate(resultSelectorContext, resultSelectorLambda.Body); ast = AstExpression.Let( var: AstExpression.VarBinding(resultSelectorSymbol.Var, ast), @in: resultSelectorTranslation.Ast); serializer = context.KnownSerializersRegistry.GetSerializer(resultSelectorLambda); } return(new AggregationExpression(expression, ast, serializer)); } } throw new ExpressionNotSupportedException(expression); }
public static AggregationExpression Translate(TranslationContext context, MethodCallExpression expression) { var method = expression.Method; var parameters = method.GetParameters(); var arguments = expression.Arguments.ToArray(); if (method.IsOneOf(__windowMethods)) { var partitionExpression = arguments[0]; var partitionTranslation = ExpressionToAggregationExpressionTranslator.TranslateEnumerable(context, partitionExpression); var partitionSerializer = (ISetWindowFieldsPartitionSerializer)partitionTranslation.Serializer; var inputSerializer = partitionSerializer.InputSerializer; AstWindow window = null; if (HasArgument <Expression>(parameters, "window", arguments, out var windowExpression)) { window = TranslateWindow(context, expression, windowExpression, inputSerializer); } if (method.IsOneOf(__nullaryMethods)) { var @operator = GetNullaryWindowOperator(method); var ast = AstExpression.NullaryWindowExpression(@operator, window); var serializer = BsonSerializer.LookupSerializer(method.ReturnType); // TODO: use correct serializer return(new AggregationExpression(expression, ast, serializer)); } AggregationExpression selectorTranslation = null; if (HasArgument <LambdaExpression>(parameters, "selector", arguments, out var selectorLambda)) { selectorTranslation = TranslateSelector(context, selectorLambda, inputSerializer); } if (method.IsOneOf(__unaryMethods)) { var @operator = GetUnaryWindowOperator(method); var ast = AstExpression.UnaryWindowExpression(@operator, selectorTranslation.Ast, window); var serializer = BsonSerializer.LookupSerializer(method.ReturnType); // TODO: use correct serializer return(new AggregationExpression(expression, ast, serializer)); } if (method.IsOneOf(__binaryMethods)) { var selector1Lambda = GetArgument <LambdaExpression>(parameters, "selector1", arguments); var selector2Lambda = GetArgument <LambdaExpression>(parameters, "selector2", arguments); var selector1Translation = TranslateSelector(context, selector1Lambda, inputSerializer); var selector2Translation = TranslateSelector(context, selector2Lambda, inputSerializer); var @operator = GetBinaryWindowOperator(method); var ast = AstExpression.BinaryWindowExpression(@operator, selector1Translation.Ast, selector2Translation.Ast, window); var serializer = BsonSerializer.LookupSerializer(method.ReturnType); // TODO: use correct serializer return(new AggregationExpression(expression, ast, serializer)); } if (method.IsOneOf(__derivativeOrIntegralMethods)) { WindowTimeUnit?unit = default; if (HasArgument <Expression>(parameters, "unit", arguments, out var unitExpression)) { unit = unitExpression.GetConstantValue <WindowTimeUnit>(expression); } var @operator = GetDerivativeOrIntegralWindowOperator(method); var ast = AstExpression.DerivativeOrIntegralWindowExpression(@operator, selectorTranslation.Ast, unit, window); var serializer = BsonSerializer.LookupSerializer(method.ReturnType); // TODO: use correct serializer return(new AggregationExpression(expression, ast, serializer)); } if (method.IsOneOf(__exponentialMovingAverageMethods)) { var weightingExpression = arguments[2]; var weighting = weightingExpression.GetConstantValue <ExponentialMovingAverageWeighting>(expression); var ast = AstExpression.ExponentialMovingAverageWindowExpression(selectorTranslation.Ast, weighting, window); var serializer = BsonSerializer.LookupSerializer(method.ReturnType); // TODO: use correct serializer return(new AggregationExpression(expression, ast, serializer)); } if (method.IsOneOf(__shiftMethods)) { var byExpression = arguments[2]; var by = byExpression.GetConstantValue <int>(expression); AstExpression defaultValue = null; if (method.Is(WindowMethod.ShiftWithDefaultValue)) { var defaultValueExpression = arguments[3]; var defaultValueTranslation = ExpressionToAggregationExpressionTranslator.Translate(context, defaultValueExpression); defaultValue = defaultValueTranslation.Ast; } var ast = AstExpression.ShiftWindowExpression(selectorTranslation.Ast, by, defaultValue); var serializer = BsonSerializer.LookupSerializer(method.ReturnType); // TODO: use correct serializer return(new AggregationExpression(expression, ast, serializer)); } } throw new ExpressionNotSupportedException(expression); }