Ejemplo n.º 1
0
        public static AstFilter Translate(TranslationContext context, ParameterExpression expression)
        {
            if (expression.Type == typeof(bool))
            {
                if (context.SymbolTable.TryGetSymbol(expression, out var symbol))
                {
                    var serializer = context.KnownSerializersRegistry.GetSerializer(expression);
                    var field      = AstFilter.Field(symbol.Name, serializer);
                    return(AstFilter.Eq(field, true));
                }
            }

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

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

                IBsonSerializer valueSerializer;
                if (pipeline.OutputSerializer is IWrappedValueSerializer wrappedValueSerializer)
                {
                    valueSerializer = wrappedValueSerializer.ValueSerializer;
                }
                else
                {
                    valueSerializer        = pipeline.OutputSerializer;
                    wrappedValueSerializer = WrappedValueSerializer.Create("_v", valueSerializer);
                    pipeline = pipeline.AddStages(
                        wrappedValueSerializer,
                        AstStage.Project(
                            AstProject.ExcludeId(),
                            AstProject.Set("_v", AstExpression.Var("ROOT"))));
                }

                var itemExpression  = arguments[1];
                var itemValue       = itemExpression.GetConstantValue <object>(containingExpression: expression);
                var serializedValue = SerializationHelper.SerializeValue(pipeline.OutputSerializer, itemValue);

                AstFilter filter = AstFilter.Eq(AstFilter.Field("_v", valueSerializer), serializedValue);
                pipeline = pipeline.AddStages(
                    __outputSerializer,
                    AstStage.Match(filter),
                    AstStage.Limit(1),
                    AstStage.Project(
                        AstProject.ExcludeId(),
                        AstProject.Set("_v", BsonNull.Value)));

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

            throw new ExpressionNotSupportedException(expression);
        }
Ejemplo n.º 3
0
        public static (AstFilterField, AstFilter) Translate(TranslationContext context, Expression sourceExpression)
        {
            if (sourceExpression is MethodCallExpression sourceMethodCallExpression)
            {
                var method    = sourceMethodCallExpression.Method;
                var arguments = sourceMethodCallExpression.Arguments;

                if (method.Is(EnumerableMethod.OfType))
                {
                    var ofTypeSourceExpression = arguments[0];
                    var(sourceField, sourceFilter) = Translate(context, ofTypeSourceExpression);

                    var nominalType                    = ArraySerializerHelper.GetItemSerializer(sourceField.Serializer).ValueType;
                    var actualType                     = method.GetGenericArguments()[0];
                    var discriminatorConvention        = BsonSerializer.LookupDiscriminatorConvention(actualType);
                    var discriminatorField             = AstFilter.Field(discriminatorConvention.ElementName, BsonValueSerializer.Instance);
                    var discriminatorValue             = discriminatorConvention.GetDiscriminator(nominalType, actualType);
                    var ofTypeFilter                   = AstFilter.Eq(discriminatorField, discriminatorValue);
                    var actualTypeSerializer           = context.KnownSerializersRegistry.GetSerializer(sourceExpression);
                    var enumerableActualTypeSerializer = IEnumerableSerializer.Create(actualTypeSerializer);
                    var actualTypeSourceField          = AstFilter.Field(sourceField.Path, enumerableActualTypeSerializer);
                    var combinedFilter                 = AstFilter.Combine(sourceFilter, ofTypeFilter);

                    return(actualTypeSourceField, combinedFilter);
                }

                if (method.Is(EnumerableMethod.Where))
                {
                    var whereSourceExpression = arguments[0];
                    var(sourceField, sourceFilter) = Translate(context, whereSourceExpression);

                    var predicateLambda     = (LambdaExpression)arguments[1];
                    var parameterExpression = predicateLambda.Parameters.Single();
                    var itemSerializer      = ArraySerializerHelper.GetItemSerializer(sourceField.Serializer);
                    var parameterSymbol     = context.CreateSymbol(parameterExpression, "@<elem>", itemSerializer); // @<elem> represents the implied element
                    var predicateContext    = context.WithSingleSymbol(parameterSymbol);                            // @<elem> is the only symbol visible inside an $elemMatch
                    var whereFilter         = ExpressionToFilterTranslator.Translate(predicateContext, predicateLambda.Body, exprOk: false);
                    var combinedFilter      = AstFilter.Combine(sourceFilter, whereFilter);

                    return(sourceField, combinedFilter);
                }
            }

            var field = ExpressionToFilterFieldTranslator.Translate(context, sourceExpression);

            return(field, null);
        }
Ejemplo n.º 4
0
        private static AstFilter Translate(TranslationContext context, Expression expression, Expression sourceExpression, Expression itemExpression)
        {
            if (itemExpression.NodeType == ExpressionType.Constant)
            {
                var sourceField     = ExpressionToFilterFieldTranslator.Translate(context, sourceExpression);
                var itemSerializer  = ArraySerializerHelper.GetItemSerializer(sourceField.Serializer);
                var value           = itemExpression.GetConstantValue <object>(containingExpression: expression);
                var serializedValue = SerializationHelper.SerializeValue(itemSerializer, value);
                return(AstFilter.ElemMatch(sourceField, AstFilter.Eq(AstFilter.Field("@<elem>", itemSerializer), serializedValue))); // @<elem> represents the implied element
            }

            var itemField        = ExpressionToFilterFieldTranslator.Translate(context, itemExpression);
            var sourceValues     = sourceExpression.GetConstantValue <IEnumerable>(containingExpression: expression);
            var serializedValues = SerializationHelper.SerializeValues(itemField.Serializer, sourceValues);

            return(AstFilter.In(itemField, serializedValues));
        }
Ejemplo n.º 5
0
        public static AstFilter Translate(TranslationContext context, TypeBinaryExpression expression)
        {
            if (expression.NodeType == ExpressionType.TypeIs)
            {
                var fieldExpression = expression.Expression;
                var field           = ExpressionToFilterFieldTranslator.Translate(context, fieldExpression);

                var nominalType             = fieldExpression.Type;
                var actualType              = expression.TypeOperand;
                var discriminatorConvention = BsonSerializer.LookupDiscriminatorConvention(actualType);
                var discriminatorField      = field.SubField(discriminatorConvention.ElementName, BsonValueSerializer.Instance);
                var discriminator           = discriminatorConvention.GetDiscriminator(nominalType, actualType);

                return(AstFilter.Eq(discriminatorField, discriminator));
            }

            throw new ExpressionNotSupportedException(expression);
        }
        private static AstFilter TranslateUsingQueryOperators(TranslationContext context, Expression expression)
        {
            switch (expression.NodeType)
            {
            case ExpressionType.And:
            case ExpressionType.AndAlso:
                return(AndExpressionToFilterTranslator.Translate(context, (BinaryExpression)expression));

            case ExpressionType.Call:
                return(MethodCallExpressionToFilterTranslator.Translate(context, (MethodCallExpression)expression));

            case ExpressionType.Equal:
            case ExpressionType.GreaterThan:
            case ExpressionType.GreaterThanOrEqual:
            case ExpressionType.LessThan:
            case ExpressionType.LessThanOrEqual:
            case ExpressionType.NotEqual:
                return(ComparisonExpressionToFilterTranslator.Translate(context, (BinaryExpression)expression));

            case ExpressionType.MemberAccess:
                return(MemberExpressionToFilterTranslator.Translate(context, (MemberExpression)expression));

            case ExpressionType.Not:
                return(NotExpressionToFilterTranslator.Translate(context, (UnaryExpression)expression));

            case ExpressionType.Or:
            case ExpressionType.OrElse:
                return(OrExpressionToFilterTranslator.Translate(context, (BinaryExpression)expression));

            case ExpressionType.Parameter:
                return(ParameterExpressionToFilterTranslator.Translate(context, (ParameterExpression)expression));

            case ExpressionType.TypeIs:
                return(TypeIsExpressionToFilterTranslator.Translate(context, (TypeBinaryExpression)expression));
            }

            if (expression.Type == typeof(bool))
            {
                var field = ExpressionToFilterFieldTranslator.Translate(context, expression);
                return(AstFilter.Eq(field, true));
            }

            throw new ExpressionNotSupportedException(expression);
        }
Ejemplo n.º 7
0
        public static AstFilter Translate(TranslationContext context, MemberExpression expression)
        {
            var memberInfo = expression.Member;

            if (memberInfo is PropertyInfo propertyInfo)
            {
                if (propertyInfo.Is(NullableProperty.HasValue))
                {
                    var fieldExpression = expression.Expression;
                    var field           = ExpressionToFilterFieldTranslator.Translate(context, fieldExpression);
                    return(AstFilter.Ne(field, BsonNull.Value));
                }

                if (propertyInfo.PropertyType == typeof(bool))
                {
                    var field = ExpressionToFilterFieldTranslator.Translate(context, expression);
                    return(AstFilter.Eq(field, true));
                }
            }

            throw new ExpressionNotSupportedException(expression);
        }
Ejemplo n.º 8
0
        // public static methods
        public static AstPipeline Translate(TranslationContext context, MethodCallExpression expression)
        {
            var method    = expression.Method;
            var arguments = expression.Arguments;

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

                var sourceType                   = sourceExpression.Type;
                var nominalType                  = sourceType.GetGenericArguments()[0];
                var actualType                   = method.GetGenericArguments()[0];
                var discriminatorConvention      = BsonSerializer.LookupDiscriminatorConvention(nominalType);
                var discriminatorElementName     = discriminatorConvention.ElementName;
                var wrappedValueOutputSerializer = pipeline.OutputSerializer as IWrappedValueSerializer;
                if (wrappedValueOutputSerializer != null)
                {
                    discriminatorElementName = wrappedValueOutputSerializer.FieldName + "." + discriminatorElementName;
                }
                var discriminatorField = AstFilter.Field(discriminatorElementName, BsonValueSerializer.Instance);
                var discriminatorValue = discriminatorConvention.GetDiscriminator(nominalType, actualType);
                var filter             = AstFilter.Eq(discriminatorField, discriminatorValue); // note: OfType only works with hierarchical discriminators
                var actualSerializer   = context.KnownSerializersRegistry.GetSerializer(expression);
                if (wrappedValueOutputSerializer != null)
                {
                    actualSerializer = WrappedValueSerializer.Create(wrappedValueOutputSerializer.FieldName, actualSerializer);
                }

                pipeline = pipeline.AddStages(
                    actualSerializer,
                    AstStage.Match(filter));

                return(pipeline);
            }

            throw new ExpressionNotSupportedException(expression);
        }
        private static AstFilter TranslateComparisonToBooleanConstant(TranslationContext context, Expression expression, Expression leftExpression, AstComparisonFilterOperator comparisonOperator, bool comparand)
        {
            var filter = ExpressionToFilterTranslator.Translate(context, leftExpression);

            if (filter is AstFieldOperationFilter fieldOperationFilter &&
                fieldOperationFilter.Operation is AstComparisonFilterOperation comparisonOperation &&
                comparisonOperation.Operator == AstComparisonFilterOperator.Eq &&
                comparisonOperation.Value == true)
            {
                var field = fieldOperationFilter.Field;

                switch (comparisonOperator)
                {
                case AstComparisonFilterOperator.Eq:
                    return(AstFilter.Eq(field, comparand));

                case AstComparisonFilterOperator.Ne:
                    return(AstFilter.Ne(field, comparand));

                default:
                    throw new ExpressionNotSupportedException(expression);
                }
            }
        private static AstFilter Translate(TranslationContext context, Expression expression, Expression expression1, Expression expression2)
        {
            Expression fieldExpression, valueExpression;

            if (expression1.NodeType == ExpressionType.Constant && expression2.NodeType != ExpressionType.Constant)
            {
                (fieldExpression, valueExpression) = (expression2, expression1);
            }
            else
            {
                (fieldExpression, valueExpression) = (expression1, expression2);
            }

            if (StringExpressionToRegexFilterTranslator.TryTranslateComparisonExpression(context, expression, fieldExpression, AstComparisonFilterOperator.Eq, valueExpression, out var filter))
            {
                return(filter);
            }

            var field           = ExpressionToFilterFieldTranslator.Translate(context, fieldExpression);
            var value           = valueExpression.GetConstantValue <object>(containingExpression: expression);
            var serializedValue = SerializationHelper.SerializeValue(field.Serializer, value);

            return(AstFilter.Eq(field, serializedValue));
        }