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);
        }
Exemple #2
0
        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);
        }
Exemple #5
0
        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()));
        }
Exemple #6
0
        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);
        }
Exemple #8
0
        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);
        }
Exemple #10
0
        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);
        }
Exemple #11
0
        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);
        }
Exemple #13
0
        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);
        }
Exemple #14
0
        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);
        }
Exemple #16
0
        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);
        }
Exemple #17
0
        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);
        }
Exemple #18
0
        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);
        }
Exemple #19
0
        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);
        }