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);
        }
Esempio n. 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 methods
        public static AstPipeline Translate(TranslationContext context, MethodCallExpression expression)
        {
            var method    = expression.Method;
            var arguments = expression.Arguments;

            if (method.IsOneOf(__groupByMethods))
            {
                var sourceExpression = arguments[0];
                var pipeline         = ExpressionToPipelineTranslator.Translate(context, sourceExpression);
                var sourceSerializer = pipeline.OutputSerializer;

                var keySelectorLambda      = ExpressionHelper.UnquoteLambda(arguments[1]);
                var keySelectorTranslation = ExpressionToAggregationExpressionTranslator.TranslateLambdaBody(context, keySelectorLambda, sourceSerializer, asRoot: true);
                var keySerializer          = keySelectorTranslation.Serializer;

                var(elementAst, elementSerializer) = TranslateElement(context, method, arguments, sourceSerializer);

                var groupingSerializer = IGroupingSerializer.Create(keySerializer, elementSerializer);
                pipeline = pipeline.AddStages(
                    groupingSerializer,
                    AstStage.Group(
                        id: keySelectorTranslation.Ast,
                        fields: AstExpression.AccumulatorField("_elements", AstAccumulatorOperator.Push, elementAst)));

                if (method.IsOneOf(__groupByWithResultSelectorMethods))
                {
                    pipeline = TranslateResultSelector(context, pipeline, arguments, keySerializer, elementSerializer);
                }

                return(pipeline);
            }

            throw new ExpressionNotSupportedException(expression);
        }
Esempio n. 4
0
        public static AggregationExpression Translate(TranslationContext context, MethodCallExpression expression)
        {
            var method    = expression.Method;
            var arguments = expression.Arguments;

            if (method.IsOneOf(__startsWithContainsOrEndWithMethods))
            {
                var  objectExpression  = expression.Object;
                var  objectTranslation = ExpressionToAggregationExpressionTranslator.Translate(context, objectExpression);
                var  valueExpression   = arguments[0];
                var  valueTranslation  = ExpressionToAggregationExpressionTranslator.Translate(context, valueExpression);
                bool ignoreCase        = false;
                if (method.IsOneOf(__withComparisonTypeMethods))
                {
                    var comparisonTypeExpression = arguments[1];
                    ignoreCase = GetIgnoreCaseFromComparisonType(comparisonTypeExpression);
                }
                if (method.IsOneOf(__withIgnoreCaseAndCultureMethods))
                {
                    var ignoreCaseExpression = arguments[1];
                    var cultureExpression    = arguments[2];
                    ignoreCase = GetIgnoreCaseFromIgnoreCaseAndCulture(ignoreCaseExpression, cultureExpression);
                }
                var stringAst    = objectTranslation.Ast;
                var substringAst = valueTranslation.Ast;
                if (ignoreCase)
                {
                    stringAst    = AstExpression.ToLower(stringAst);
                    substringAst = AstExpression.ToLower(stringAst);
                }
                var ast = CreateAst(method.Name, stringAst, substringAst);
                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.IsOneOf(__dateTimeSubtractWithDateTimeMethods))
            {
                Expression thisExpression, valueExpression;
                if (method.IsStatic)
                {
                    thisExpression  = arguments[0];
                    valueExpression = arguments[1];
                }
                else
                {
                    thisExpression  = expression.Object;
                    valueExpression = arguments[0];
                }

                var thisTranslation  = ExpressionToAggregationExpressionTranslator.Translate(context, thisExpression);
                var valueTranslation = ExpressionToAggregationExpressionTranslator.Translate(context, valueExpression);

                AstExpression   unit, startOfWeek;
                IBsonSerializer serializer;
                if (method.IsOneOf(__dateTimeSubtractWithUnitMethods))
                {
                    var unitExpression = arguments[2];
                    var unitConstant   = unitExpression.GetConstantValue <DateTimeUnit>(containingExpression: expression);
                    unit = unitConstant.Unit;
                    if (unitConstant is WeekWithStartOfWeekDayTimeUnit unitConstantWithStartOfWeek)
                    {
                        startOfWeek = unitConstantWithStartOfWeek.StartOfWeek;
                    }
                    else
                    {
                        startOfWeek = null;
                    }
                    serializer = BsonInt64Serializer.Instance;
                }
                else
                {
                    unit        = "millisecond";
                    startOfWeek = null;
                    serializer  = new TimeSpanSerializer(representation: BsonType.Int64, units: TimeSpanUnits.Milliseconds);
                }

                AstExpression timezone = null;
                if (method.IsOneOf(__dateTimeSubtractWithTimezoneMethods))
                {
                    var timezoneExpression  = arguments.Last();
                    var timezoneTranslation = ExpressionToAggregationExpressionTranslator.Translate(context, timezoneExpression);
                    timezone = timezoneTranslation.Ast;
                }

                var ast = AstExpression.DateDiff(valueTranslation.Ast, thisTranslation.Ast, unit, timezone, startOfWeek);
                return(new AggregationExpression(expression, ast, serializer));
            }

            throw new ExpressionNotSupportedException(expression);
        }
        private static (AstExpression, IBsonSerializer) TranslateElement(
            TranslationContext context,
            MethodInfo method,
            ReadOnlyCollection <Expression> arguments,
            IBsonSerializer sourceSerializer)
        {
            AstExpression   elementAst;
            IBsonSerializer elementSerializer;

            if (method.IsOneOf(__groupByWithElementSelectorMethods))
            {
                var elementLambda      = ExpressionHelper.UnquoteLambda(arguments[2]);
                var elementTranslation = ExpressionToAggregationExpressionTranslator.TranslateLambdaBody(context, elementLambda, sourceSerializer, asRoot: true);
                elementAst        = elementTranslation.Ast;
                elementSerializer = elementTranslation.Serializer;
            }
            else
            {
                var rootVar = AstExpression.Var("ROOT", isCurrent: true);

                if (sourceSerializer is IWrappedValueSerializer wrappedSerializer)
                {
                    elementAst        = AstExpression.GetField(rootVar, wrappedSerializer.FieldName);
                    elementSerializer = wrappedSerializer.ValueSerializer;
                }
                else
                {
                    elementAst        = rootVar;
                    elementSerializer = sourceSerializer;
                }
            }

            return(elementAst, elementSerializer);
        }
        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);
        }
Esempio n. 8
0
        private static AstPipeline TranslateSelectManyWithCollectionSelectorAndNonIdentityResultSelector(
            TranslationContext context,
            AstPipeline pipeline,
            AggregationExpression collectionSelectorTranslation,
            LambdaExpression resultSelectorLambda)

        {
            var sourceSerializer         = pipeline.OutputSerializer;
            var collectionItemSerializer = ArraySerializerHelper.GetItemSerializer(collectionSelectorTranslation.Serializer);

            var resultSelectorSourceParameterExpression = resultSelectorLambda.Parameters[0];
            var resultSelectorSourceAst                         = AstExpression.Var("ROOT", isCurrent: true);
            var resultSelectorSourceParameterSymbol             = context.CreateSymbol(resultSelectorSourceParameterExpression, resultSelectorSourceAst, sourceSerializer, isCurrent: true);
            var resultSelectorCollectionItemParameterExpression = resultSelectorLambda.Parameters[1];
            var resultSelectorCollectionItemParameterSymbol     = context.CreateSymbol(resultSelectorCollectionItemParameterExpression, collectionItemSerializer);
            var resultSelectorContext        = context.WithSymbols(resultSelectorSourceParameterSymbol, resultSelectorCollectionItemParameterSymbol);
            var resultSelectorTranslation    = ExpressionToAggregationExpressionTranslator.Translate(resultSelectorContext, resultSelectorLambda.Body);
            var resultValueSerializer        = resultSelectorTranslation.Serializer;
            var resultWrappedValueSerializer = WrappedValueSerializer.Create("_v", resultValueSerializer);
            var resultAst = AstExpression.Map(
                input: collectionSelectorTranslation.Ast,
                @as: resultSelectorCollectionItemParameterSymbol.Var,
                @in: resultSelectorTranslation.Ast);

            return(pipeline.AddStages(
                       resultWrappedValueSerializer,
                       AstStage.Project(
                           AstProject.Set("_v", resultAst),
                           AstProject.ExcludeId()),
                       AstStage.Unwind("_v")));
        }
        private static AggregationExpression TranslateHelper(TranslationContext context, Expression expression, Expression stringExpression, Expression startIndexExpression, Expression lengthExpression, AstTernaryOperator substrOperator)
        {
            var stringTranslation     = ExpressionToAggregationExpressionTranslator.Translate(context, stringExpression);
            var startIndexTranslation = ExpressionToAggregationExpressionTranslator.Translate(context, startIndexExpression);

            AstExpression ast;

            if (lengthExpression == null)
            {
                var strlenOperator = substrOperator == AstTernaryOperator.SubstrCP ? AstUnaryOperator.StrLenCP : AstUnaryOperator.StrLenBytes;
                var(stringVar, stringAst) = AstExpression.UseVarIfNotSimple("string", stringTranslation.Ast);
                var(indexVar, indexAst)   = AstExpression.UseVarIfNotSimple("index", startIndexTranslation.Ast);
                var lengthAst = AstExpression.StrLen(strlenOperator, stringAst);
                var countAst  = AstExpression.Subtract(lengthAst, indexAst);
                var inAst     = AstExpression.Substr(substrOperator, stringAst, indexAst, countAst);
                ast = AstExpression.Let(stringVar, indexVar, inAst);
            }
            else
            {
                var lengthTranslation = ExpressionToAggregationExpressionTranslator.Translate(context, lengthExpression);
                ast = AstExpression.Substr(substrOperator, stringTranslation.Ast, startIndexTranslation.Ast, lengthTranslation.Ast);
            }

            return(new AggregationExpression(expression, ast, new StringSerializer()));
        }
        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.Translate(context, firstExpression);
                var secondExpression          = arguments[1];
                var secondTranslation         = ExpressionToAggregationExpressionTranslator.Translate(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("z__");
                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 methods
        public static AstPipeline Translate(TranslationContext context, MethodCallExpression expression)
        {
            var method    = expression.Method;
            var arguments = expression.Arguments;

            if (method.Is(QueryableMethod.Select))
            {
                var sourceExpression = arguments[0];
                var pipeline         = ExpressionToPipelineTranslator.Translate(context, sourceExpression);
                var sourceSerializer = pipeline.OutputSerializer;

                var selectorLambda = ExpressionHelper.UnquoteLambda(arguments[1]);
                if (selectorLambda.Body == selectorLambda.Parameters[0])
                {
                    return(pipeline); // ignore identity projection: Select(x => x)
                }

                var selectorTranslation = ExpressionToAggregationExpressionTranslator.TranslateLambdaBody(context, selectorLambda, sourceSerializer, asRoot: true);
                var(projectStage, projectionSerializer) = ProjectionHelper.CreateProjectStage(selectorTranslation);
                pipeline = pipeline.AddStages(projectionSerializer, projectStage);

                return(pipeline);
            }

            throw new ExpressionNotSupportedException(expression);
        }
        public static AggregationExpression Translate(TranslationContext context, MethodCallExpression expression)
        {
            var method    = expression.Method;
            var arguments = expression.Arguments;

            if (method.IsOneOf(MathMethod.Log, MathMethod.LogWithNewBase, MathMethod.Log10))
            {
                var           argumentExpression  = ConvertHelper.RemoveWideningConvert(arguments[0]);
                var           argumentTranslation = ExpressionToAggregationExpressionTranslator.Translate(context, argumentExpression);
                AstExpression ast;
                if (method.Is(MathMethod.LogWithNewBase))
                {
                    var newBaseExpression  = arguments[1];
                    var newBaseTranslation = ExpressionToAggregationExpressionTranslator.Translate(context, newBaseExpression);
                    ast = AstExpression.Log(argumentTranslation.Ast, newBaseTranslation.Ast);
                }
                else
                {
                    ast = method.Is(MathMethod.Log10) ?
                          AstExpression.Log10(argumentTranslation.Ast) :
                          AstExpression.Ln(argumentTranslation.Ast);
                }
                return(new AggregationExpression(expression, ast, new DoubleSerializer()));
            }

            throw new ExpressionNotSupportedException(expression);
        }
Esempio n. 13
0
        private static AggregationExpression TranslateDateTimeParse(TranslationContext context, MethodCallExpression expression)
        {
            var stringExpression  = expression.Arguments[0];
            var stringTranslation = ExpressionToAggregationExpressionTranslator.Translate(context, stringExpression);
            var ast = AstExpression.DateFromString(stringTranslation.Ast);

            return(new AggregationExpression(expression, ast, new DateTimeSerializer()));
        }
Esempio n. 14
0
        private static AggregationExpression TranslateEnumerableContains(TranslationContext context, Expression expression, Expression sourceExpression, Expression valueExpression)
        {
            var sourceTranslation = ExpressionToAggregationExpressionTranslator.Translate(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 methods
        public static AstPipeline Translate(TranslationContext context, MethodCallExpression expression)
        {
            var method    = expression.Method;
            var arguments = expression.Arguments;

            if (method.Is(QueryableMethod.Join))
            {
                var outerExpression = arguments[0];
                var pipeline        = ExpressionToPipelineTranslator.Translate(context, outerExpression);
                var outerSerializer = pipeline.OutputSerializer;

                var wrapOuterStage = AstStage.Project(
                    AstProject.Set("_outer", AstExpression.Var("ROOT")),
                    AstProject.ExcludeId());
                var wrappedOuterSerializer = WrappedValueSerializer.Create("_outer", outerSerializer);

                var innerExpression = arguments[1];
                var(innerCollectionName, innerSerializer) = innerExpression.GetCollectionInfo(containerExpression: expression);

                var outerKeySelectorLambda = ExpressionHelper.UnquoteLambda(arguments[2]);
                var localFieldPath         = outerKeySelectorLambda.GetFieldPath(context, wrappedOuterSerializer);

                var innerKeySelectorLambda = ExpressionHelper.UnquoteLambda(arguments[3]);
                var foreignFieldPath       = innerKeySelectorLambda.GetFieldPath(context, innerSerializer);

                var lookupStage = AstStage.Lookup(
                    from: innerCollectionName,
                    match: new AstLookupStageEqualityMatch(localFieldPath, foreignFieldPath),
                    @as: "_inner");

                var unwindStage = AstStage.Unwind("_inner");

                var resultSelectorLambda = ExpressionHelper.UnquoteLambda(arguments[4]);
                var root                      = AstExpression.Var("ROOT", isCurrent: true);
                var outerParameter            = resultSelectorLambda.Parameters[0];
                var outerField                = AstExpression.GetField(root, "_outer");
                var outerSymbol               = context.CreateSymbol(outerParameter, outerField, outerSerializer);
                var innerParameter            = resultSelectorLambda.Parameters[1];
                var innerField                = AstExpression.GetField(root, "_inner");
                var innerSymbol               = context.CreateSymbol(innerParameter, innerField, innerSerializer);
                var resultSelectorContext     = context.WithSymbols(outerSymbol, innerSymbol);
                var resultSelectorTranslation = ExpressionToAggregationExpressionTranslator.Translate(resultSelectorContext, resultSelectorLambda.Body);
                var(projectStage, newOutputSerializer) = ProjectionHelper.CreateProjectStage(resultSelectorTranslation);

                pipeline = pipeline.AddStages(
                    newOutputSerializer,
                    wrapOuterStage,
                    lookupStage,
                    unwindStage,
                    projectStage);

                return(pipeline);
            }

            throw new ExpressionNotSupportedException(expression);
        }
        // public static methods
        public static ExecutableQuery <TDocument, TOutput> Translate <TDocument>(MongoQueryProvider <TDocument> provider, TranslationContext context, MethodCallExpression expression)
        {
            var method    = expression.Method;
            var arguments = expression.Arguments;

            if (method.IsOneOf(__averageMethods))
            {
                var sourceExpression = arguments[0];
                var pipeline         = ExpressionToPipelineTranslator.Translate(context, sourceExpression);
                var sourceSerializer = pipeline.OutputSerializer;

                AstExpression valueExpression;
                if (method.IsOneOf(__averageWithSelectorMethods))
                {
                    var selectorLambda      = ExpressionHelper.UnquoteLambda(arguments[1]);
                    var selectorTranslation = ExpressionToAggregationExpressionTranslator.TranslateLambdaBody(context, selectorLambda, sourceSerializer, asRoot: true);
                    valueExpression = selectorTranslation.Ast;
                }
                else
                {
                    Ensure.That(sourceSerializer is IWrappedValueSerializer, "Expected sourceSerializer to be an IWrappedValueSerializer.", nameof(sourceSerializer));
                    var root = AstExpression.Var("ROOT", isCurrent: true);
                    valueExpression = AstExpression.GetField(root, "_v");
                }

                IBsonSerializer outputValueSerializer = expression.GetResultType() 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)
                };
                var outputWrappedValueSerializer = WrappedValueSerializer.Create("_v", outputValueSerializer);

                pipeline = pipeline.AddStages(
                    outputWrappedValueSerializer,
                    AstStage.Group(
                        id: BsonNull.Value,
                        fields: AstExpression.AccumulatorField("_v", AstAccumulatorOperator.Avg, valueExpression)),
                    AstStage.Project(AstProject.ExcludeId()));

                return(ExecutableQuery.Create(
                           provider.Collection,
                           provider.Options,
                           pipeline,
                           __finalizer));
            }

            throw new ExpressionNotSupportedException(expression);
        }
    }
        private static AggregationExpression TranslateInstanceEqualsMethod(TranslationContext context, MethodCallExpression expression)
        {
            var lhsExpression  = expression.Object;
            var lhsTranslation = ExpressionToAggregationExpressionTranslator.Translate(context, lhsExpression);
            var rhsExpression  = expression.Arguments[0];
            var rhsTranslation = ExpressionToAggregationExpressionTranslator.Translate(context, rhsExpression);
            var ast            = AstExpression.Eq(lhsTranslation.Ast, rhsTranslation.Ast);

            return(new AggregationExpression(expression, ast, new BooleanSerializer()));
        }
Esempio n. 18
0
        public static AggregationExpression Translate(TranslationContext context, MethodCallExpression expression)
        {
            var method    = expression.Method;
            var arguments = expression.Arguments;

            if (method.IsOneOf(DateTimeMethod.Truncate, DateTimeMethod.TruncateWithBinSize, DateTimeMethod.TruncateWithBinSizeAndTimezone))
            {
                var dateExpression  = arguments[0];
                var dateTranslation = ExpressionToAggregationExpressionTranslator.Translate(context, dateExpression);

                var           unitExpression = arguments[1];
                var           unitConstant   = unitExpression.GetConstantValue <DateTimeUnit>(expression);
                AstExpression unit           = unitConstant.Unit;
                AstExpression startOfWeek;
                if (unitConstant is WeekWithStartOfWeekDayTimeUnit unitConstantWithStartOfWeek)
                {
                    startOfWeek = unitConstantWithStartOfWeek.StartOfWeek;
                }
                else
                {
                    startOfWeek = null;
                }

                AstExpression binSize = null;
                if (method.IsOneOf(DateTimeMethod.TruncateWithBinSize, DateTimeMethod.TruncateWithBinSizeAndTimezone))
                {
                    var binSizeExpression = arguments[2];
                    binSizeExpression = ConvertHelper.RemoveWideningConvert(binSizeExpression);
                    var binSizeTranslation = ExpressionToAggregationExpressionTranslator.Translate(context, binSizeExpression);
                    binSize = binSizeTranslation.Ast;
                }

                AstExpression timezone = null;
                if (method.Is(DateTimeMethod.TruncateWithBinSizeAndTimezone))
                {
                    var timezoneExpression  = arguments[3];
                    var timezoneTranslation = ExpressionToAggregationExpressionTranslator.Translate(context, timezoneExpression);
                    timezone = timezoneTranslation.Ast;
                }

                var ast        = AstExpression.DateTrunc(dateTranslation.Ast, unit, binSize, timezone, startOfWeek);
                var serializer = DateTimeSerializer.UtcInstance;
                return(new AggregationExpression(expression, ast, serializer));
            }

            if (method.IsOneOf(MathMethod.TruncateDecimal, MathMethod.TruncateDouble))
            {
                var argumentExpression  = ConvertHelper.RemoveWideningConvert(arguments[0]);
                var argumentTranslation = ExpressionToAggregationExpressionTranslator.Translate(context, argumentExpression);
                var ast = AstExpression.Trunc(argumentTranslation.Ast);
                return(new AggregationExpression(expression, ast, argumentTranslation.Serializer));
            }

            throw new ExpressionNotSupportedException(expression);
        }
Esempio n. 19
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)
        {
            if (IsSetEqualsMethod(expression, out var objectExpression, out var otherExpression))
            {
                var objectTranslation = ExpressionToAggregationExpressionTranslator.Translate(context, objectExpression);
                var otherTranslation  = ExpressionToAggregationExpressionTranslator.Translate(context, otherExpression);
                var ast = AstExpression.SetEquals(objectTranslation.Ast, otherTranslation.Ast);

                return(new AggregationExpression(expression, ast, new BooleanSerializer()));
            }
            throw new ExpressionNotSupportedException(expression);
        }
        public static AggregationExpression Translate(TranslationContext context, MemberExpression expression)
        {
            if (expression.Member is PropertyInfo propertyInfo && propertyInfo.Is(NullableProperty.HasValue))
            {
                var containerExpression  = expression.Expression;
                var containerTranslation = ExpressionToAggregationExpressionTranslator.Translate(context, containerExpression);
                var ast        = AstExpression.Ne(containerTranslation.Ast, BsonNull.Value);
                var serializer = new BooleanSerializer();
                return(new AggregationExpression(expression, ast, serializer));
            }

            throw new ExpressionNotSupportedException(expression);
        }
        internal override BsonValue TranslateExpressionToAggregateExpression <TSource, TResult>(
            Expression <Func <TSource, TResult> > expression,
            IBsonSerializer <TSource> sourceSerializer,
            IBsonSerializerRegistry serializerRegistry,
            ExpressionTranslationOptions translationOptions)
        {
            expression = (Expression <Func <TSource, TResult> >)PartialEvaluator.EvaluatePartially(expression);
            var context       = TranslationContext.Create(expression, sourceSerializer);
            var translation   = ExpressionToAggregationExpressionTranslator.TranslateLambdaBody(context, expression, sourceSerializer, asRoot: true);
            var simplifiedAst = AstSimplifier.Simplify(translation.Ast);

            return(simplifiedAst.Render());
        }
        // public static methods
        public static ExecutableQuery <TDocument, TOutput> Translate <TDocument>(MongoQueryProvider <TDocument> provider, TranslationContext context, MethodCallExpression expression)
        {
            var method    = expression.Method;
            var arguments = expression.Arguments;

            if (method.IsOneOf(__maxMethods))
            {
                var sourceExpression = arguments[0];
                var pipeline         = ExpressionToPipelineTranslator.Translate(context, sourceExpression);
                var sourceSerializer = pipeline.OutputSerializer;
                var root             = AstExpression.Var("ROOT", isCurrent: true);

                AstExpression   valueAst;
                IBsonSerializer valueSerializer;
                if (method.IsOneOf(__maxWithSelectorMethods))
                {
                    var selectorLambda      = ExpressionHelper.UnquoteLambda(arguments[1]);
                    var selectorTranslation = ExpressionToAggregationExpressionTranslator.TranslateLambdaBody(context, selectorLambda, sourceSerializer, asRoot: true);
                    if (selectorTranslation.Serializer is IBsonDocumentSerializer)
                    {
                        valueAst        = selectorTranslation.Ast;
                        valueSerializer = selectorTranslation.Serializer;
                    }
                    else
                    {
                        valueAst        = AstExpression.ComputedDocument(new[] { AstExpression.ComputedField("_v", selectorTranslation.Ast) });
                        valueSerializer = WrappedValueSerializer.Create("_v", selectorTranslation.Serializer);
                    }
                }
                else
                {
                    valueAst        = root;
                    valueSerializer = pipeline.OutputSerializer;
                }

                pipeline = pipeline.AddStages(
                    valueSerializer,
                    AstStage.Group(
                        id: BsonNull.Value,
                        fields: AstExpression.AccumulatorField("_max", AstAccumulatorOperator.Max, valueAst)),
                    AstStage.ReplaceRoot(AstExpression.GetField(root, "_max")));

                return(ExecutableQuery.Create(
                           provider.Collection,
                           provider.Options,
                           pipeline,
                           __finalizer));
            }

            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);
        }
Esempio n. 25
0
        public static AggregationExpression Translate(TranslationContext context, MemberExpression expression)
        {
            // note: array.Length is not handled here but in ArrayLengthExpressionToAggregationExpressionTranslator

            if (IsStringLengthProperty(expression))
            {
                var stringExpression  = expression.Expression;
                var stringTranslation = ExpressionToAggregationExpressionTranslator.Translate(context, stringExpression);
                var ast = AstExpression.StrLenCP(stringTranslation.Ast);
                return(new AggregationExpression(expression, ast, new Int32Serializer()));
            }

            throw new ExpressionNotSupportedException(expression);
        }
        public static AggregationExpression Translate(TranslationContext context, MemberExpression expression)
        {
            if (expression.Member is PropertyInfo propertyInfo && propertyInfo.Is(NullableProperty.Value))
            {
                var containerExpression  = expression.Expression;
                var containerTranslation = ExpressionToAggregationExpressionTranslator.Translate(context, containerExpression);
                if (containerTranslation.Serializer is IChildSerializerConfigurable containerSerializer)
                {
                    return(new AggregationExpression(expression, containerTranslation.Ast, containerSerializer.ChildSerializer));
                }
            }

            throw new ExpressionNotSupportedException(expression);
        }
Esempio n. 27
0
        public static string GetFieldPath(this LambdaExpression fieldSelectorLambda, TranslationContext context, IBsonSerializer parameterSerializer)
        {
            var fieldSelectorTranslation = ExpressionToAggregationExpressionTranslator.TranslateLambdaBody(context, fieldSelectorLambda, parameterSerializer, asRoot: true);

            if (fieldSelectorTranslation.Ast.CanBeConvertedToFieldPath())
            {
                var path = fieldSelectorTranslation.Ast.ConvertToFieldPath();
                if (path.Length >= 2 && path[0] == '$' && path[1] != '$')
                {
                    return(path.Substring(1));
                }
            }

            throw new ExpressionNotSupportedException(fieldSelectorLambda);
        }
        public static AggregationExpression Translate(TranslationContext context, MethodCallExpression expression)
        {
            var method    = expression.Method;
            var arguments = expression.Arguments;

            if (method.Is(MathMethod.Exp))
            {
                var argumentExpression  = ConvertHelper.RemoveWideningConvert(arguments[0]);
                var argumentTranslation = ExpressionToAggregationExpressionTranslator.Translate(context, argumentExpression);
                var ast = AstExpression.Exp(argumentTranslation.Ast);
                return(new AggregationExpression(expression, ast, new DoubleSerializer()));
            }

            throw new ExpressionNotSupportedException(expression);
        }
        public static AggregationExpression Translate(TranslationContext context, MethodCallExpression expression)
        {
            var method    = expression.Method;
            var arguments = expression.Arguments;

            if (method.IsOneOf(__absMethods))
            {
                var valueExpression  = ConvertHelper.RemoveWideningConvert(arguments[0]);
                var valueTranslation = ExpressionToAggregationExpressionTranslator.Translate(context, valueExpression);
                var ast = AstExpression.Abs(valueTranslation.Ast);
                return(new AggregationExpression(expression, ast, valueTranslation.Serializer));
            }

            throw new ExpressionNotSupportedException(expression);
        }
Esempio n. 30
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.Translate(context, sourceExpression);
                var ast = AstExpression.SetIntersection(sourceTranslation.Ast);
                return(new AggregationExpression(expression, ast, sourceTranslation.Serializer));
            }

            throw new ExpressionNotSupportedException(expression);
        }