Example #1
0
        private static AstFilter Translate(TranslationContext context, Expression inputExpression, Regex regex)
        {
            var inputFieldAst     = ExpressionToFilterFieldTranslator.Translate(context, inputExpression);
            var regularExpression = new BsonRegularExpression(regex);

            return(AstFilter.Regex(inputFieldAst, regularExpression.Pattern, regularExpression.Options));
        }
        // caller is responsible for ensuring constant is on the right
        public static AstFilter Translate(
            TranslationContext context,
            Expression expression,
            Expression leftExpression,
            AstComparisonFilterOperator comparisonOperator,
            Expression rightExpression)
        {
            if (leftExpression is MethodCallExpression leftMethodCallExpression &&
                IsCompareToMethod(leftMethodCallExpression.Method))
            {
                var fieldExpression = leftMethodCallExpression.Object;
                var field           = ExpressionToFilterFieldTranslator.Translate(context, fieldExpression);

                var valueExpression = leftMethodCallExpression.Arguments[0];
                var value           = valueExpression.GetConstantValue <object>(containingExpression: expression);
                var serializedValue = SerializationHelper.SerializeValue(field.Serializer, value);

                var rightValue = rightExpression.GetConstantValue <int>(containingExpression: expression);
                if (rightValue == 0)
                {
                    return(AstFilter.Compare(field, comparisonOperator, serializedValue));
                }
            }

            throw new ExpressionNotSupportedException(expression);
        }
        public static AstFilter Translate(TranslationContext context, Expression arrayFieldExpression, ConstantExpression arrayConstantExpression)
        {
            var arrayFieldTranslation = ExpressionToFilterFieldTranslator.Translate(context, arrayFieldExpression);
            var itemSerializer        = ArraySerializerHelper.GetItemSerializer(arrayFieldTranslation.Serializer);
            var values           = (IEnumerable)arrayConstantExpression.Value;
            var serializedValues = SerializationHelper.SerializeValues(itemSerializer, values);

            return(AstFilter.In(arrayFieldTranslation, serializedValues));
        }
        public static AstFilter Translate(TranslationContext context, BinaryExpression expression)
        {
            var comparisonOperator = GetComparisonOperator(expression);
            var leftExpression     = expression.Left;
            var rightExpression    = expression.Right;

            if (leftExpression.NodeType == ExpressionType.Constant && rightExpression.NodeType != ExpressionType.Constant)
            {
                comparisonOperator = GetComparisonOperatorForSwappedLeftAndRight(expression);
                (leftExpression, rightExpression) = (rightExpression, leftExpression);
            }

            if (ArrayLengthComparisonExpressionToFilterTranslator.CanTranslate(leftExpression, rightExpression, out var arrayLengthExpression, out var sizeExpression))
            {
                return(ArrayLengthComparisonExpressionToFilterTranslator.Translate(context, expression, arrayLengthExpression, sizeExpression));
            }

            if (BitMaskComparisonExpressionToFilterTranslator.CanTranslate(leftExpression))
            {
                return(BitMaskComparisonExpressionToFilterTranslator.Translate(context, expression, leftExpression, comparisonOperator, rightExpression));
            }

            if (CompareToComparisonExpressionToFilterTranslator.CanTranslate(leftExpression))
            {
                return(CompareToComparisonExpressionToFilterTranslator.Translate(context, expression, leftExpression, comparisonOperator, rightExpression));
            }

            if (CountComparisonExpressionToFilterTranslator.CanTranslate(leftExpression, rightExpression, out var countExpression, out sizeExpression))
            {
                return(CountComparisonExpressionToFilterTranslator.Translate(context, expression, countExpression, sizeExpression));
            }

            if (ModuloComparisonExpressionToFilterTranslator.CanTranslate(leftExpression, rightExpression, out var moduloExpression, out var remainderExpression))
            {
                return(ModuloComparisonExpressionToFilterTranslator.Translate(context, expression, moduloExpression, remainderExpression));
            }

            if (StringExpressionToRegexFilterTranslator.CanTranslateComparisonExpression(leftExpression, comparisonOperator, rightExpression))
            {
                return(StringExpressionToRegexFilterTranslator.TranslateComparisonExpression(context, expression, leftExpression, comparisonOperator, rightExpression));
            }

            var comparand = rightExpression.GetConstantValue <object>(containingExpression: expression);

            if (leftExpression.Type == typeof(bool) &&
                (comparisonOperator == AstComparisonFilterOperator.Eq || comparisonOperator == AstComparisonFilterOperator.Ne) &&
                rightExpression.Type == typeof(bool))
            {
                return(TranslateComparisonToBooleanConstant(context, expression, leftExpression, comparisonOperator, (bool)comparand));
            }

            var field = ExpressionToFilterFieldTranslator.Translate(context, leftExpression);
            var serializedComparand = SerializationHelper.SerializeValue(field.Serializer, comparand);

            return(AstFilter.Compare(field, comparisonOperator, serializedComparand));
        }
        private static AstFilter Translate(TranslationContext context, Expression expression, Expression inputExpression, Regex regex)
        {
            var inputFieldAst     = ExpressionToFilterFieldTranslator.Translate(context, inputExpression);
            var regularExpression = new BsonRegularExpression(regex);

            if (inputFieldAst.Serializer is IRepresentationConfigurable representationConfigurable &&
                representationConfigurable.Representation != BsonType.String)
            {
                throw new ExpressionNotSupportedException(inputExpression, expression, because: $"field \"{inputFieldAst.Path}\" is not represented as a string");
            }

            return(AstFilter.Regex(inputFieldAst, regularExpression.Pattern, regularExpression.Options));
        }
        // public static methods
        public static AstFilter Translate(TranslationContext context, MethodCallExpression expression)
        {
            var method    = expression.Method;
            var arguments = expression.Arguments;

            if (method.Is(StringMethod.IsNullOrEmpty))
            {
                var fieldExpression = arguments[0];
                var field           = ExpressionToFilterFieldTranslator.Translate(context, fieldExpression);
                return(AstFilter.In(field, new BsonValue[] { BsonNull.Value, "" }));
            }

            throw new ExpressionNotSupportedException(expression);
        }
        internal override RenderedFieldDefinition TranslateExpressionToField <TDocument>(
            LambdaExpression expression,
            IBsonSerializer <TDocument> documentSerializer,
            IBsonSerializerRegistry serializerRegistry)
        {
            var parameter = expression.Parameters.Single();
            var context   = TranslationContext.Create(expression, documentSerializer);
            var symbol    = context.CreateSymbol(parameter, documentSerializer, isCurrent: true);

            context = context.WithSymbol(symbol);
            var body  = RemovePossibleConvertToObject(expression.Body);
            var field = ExpressionToFilterFieldTranslator.Translate(context, body);

            return(new RenderedFieldDefinition(field.Path, field.Serializer));
Example #8
0
        // caller is responsible for ensuring constant is on the right
        public static AstFilter Translate(
            TranslationContext context,
            Expression expression,
            Expression leftExpression,
            AstComparisonFilterOperator comparisonOperator,
            Expression rightExpression)
        {
            if (leftExpression is BinaryExpression leftBinaryExpression &&
                leftBinaryExpression.NodeType == ExpressionType.And)
            {
                var fieldExpression = leftBinaryExpression.Left;
                var field           = ExpressionToFilterFieldTranslator.Translate(context, fieldExpression);

                var bitMaskExpression = leftBinaryExpression.Right;
                var bitMask           = bitMaskExpression.GetConstantValue <object>(containingExpression: expression);
                var serializedBitMask = SerializationHelper.SerializeValue(field.Serializer, bitMask);

                var rightValue = rightExpression.GetConstantValue <object>(containingExpression: expression);
                var zeroValue  = Activator.CreateInstance(bitMask.GetType());

                switch (comparisonOperator)
                {
                case AstComparisonFilterOperator.Eq:
                    if (rightValue.Equals(zeroValue))
                    {
                        return(AstFilter.BitsAllClear(field, serializedBitMask));
                    }
                    else if (rightValue.Equals(bitMask))
                    {
                        return(AstFilter.BitsAllSet(field, serializedBitMask));
                    }
                    break;

                case AstComparisonFilterOperator.Ne:
                    if (rightValue.Equals(zeroValue))
                    {
                        return(AstFilter.BitsAnySet(field, serializedBitMask));
                    }
                    else if (rightValue.Equals(bitMask))
                    {
                        return(AstFilter.BitsAnyClear(field, serializedBitMask));
                    }
                    break;
                }
            }

            throw new ExpressionNotSupportedException(expression);
        }
Example #9
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);
        }
Example #10
0
        public static AstFilter Translate(TranslationContext context, BinaryExpression expression, Expression enumerableExpression, Expression sizeExpression)
        {
            var field = ExpressionToFilterFieldTranslator.Translate(context, enumerableExpression);

            if (TryConvertSizeExpressionToBsonValue(sizeExpression, out var size))
            {
                var compareCountFilter = AstFilter.Size(field, size);
                switch (expression.NodeType)
                {
                case ExpressionType.Equal: return(compareCountFilter);

                case ExpressionType.NotEqual: return(AstFilter.Not(compareCountFilter));
                }
            }

            throw new ExpressionNotSupportedException(expression);
        }
Example #11
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));
        }
        // public static methods
        public static AstFilter Translate(TranslationContext context, MethodCallExpression expression)
        {
            var method    = expression.Method;
            var arguments = expression.Arguments;

            if (method.Is(EnumMethod.HasFlag))
            {
                var fieldExpression = expression.Object;
                var field           = ExpressionToFilterFieldTranslator.Translate(context, fieldExpression);

                var flagExpression = arguments[0];
                var flag           = flagExpression.GetConstantValue <object>(containingExpression: expression);
                var serializedFlag = SerializationHelper.SerializeValue(field.Serializer, flag);
                return(AstFilter.BitsAllSet(field, serializedFlag));
            }

            throw new ExpressionNotSupportedException(expression);
        }
Example #13
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);
        }
Example #15
0
        public static AstFilter Translate(TranslationContext context, BinaryExpression expression, UnaryExpression arrayLengthExpression, Expression sizeExpression)
        {
            if (arrayLengthExpression.NodeType == ExpressionType.ArrayLength)
            {
                var arrayExpression = arrayLengthExpression.Operand;
                var arrayField      = ExpressionToFilterFieldTranslator.Translate(context, arrayExpression);
                var size            = sizeExpression.GetConstantValue <int>(containingExpression: expression);

                switch (expression.NodeType)
                {
                case ExpressionType.Equal:
                    return(AstFilter.Size(arrayField, size));

                case ExpressionType.NotEqual:
                    return(AstFilter.Not(AstFilter.Size(arrayField, size)));
                }
            }

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

            if (method.IsOneOf(__stringInOrNinMethods))
            {
                var fieldExpression = arguments[0];
                var field           = ExpressionToFilterFieldTranslator.Translate(context, fieldExpression);

                var valuesExpression = arguments[1];
                if (valuesExpression is ConstantExpression constantValuesExpression)
                {
                    var serializedValues = new List <BsonValue>();

                    var values                      = ((IEnumerable <StringOrRegularExpression>)constantValuesExpression.Value).ToList();
                    var stringSerializer            = StringSerializer.Instance;
                    var regularExpressionSerializer = BsonRegularExpressionSerializer.Instance;
                    foreach (var value in values)
                    {
                        BsonValue serializedValue;
                        if (value?.Type == typeof(BsonRegularExpression))
                        {
                            var regularExpression = value.RegularExpression;
                            serializedValue = SerializationHelper.SerializeValue(regularExpressionSerializer, regularExpression);
                        }
                        else
                        {
                            var @string = value?.String;
                            serializedValue = SerializationHelper.SerializeValue(stringSerializer, @string);
                        }
                        serializedValues.Add(serializedValue);
                    }

                    return(method.IsOneOf(__stringInMethods) ? AstFilter.In(field, serializedValues) : AstFilter.Nin(field, serializedValues));
                }
            }

            throw new ExpressionNotSupportedException(expression);
        }
Example #17
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);
        }
        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));
        }
Example #19
0
        public static AstFilter Translate(TranslationContext context, BinaryExpression expression, BinaryExpression moduloExpression, Expression remainderExpression)
        {
            var fieldExpression = moduloExpression.Left;
            var field           = ExpressionToFilterFieldTranslator.Translate(context, fieldExpression);

            var       divisorExpression = moduloExpression.Right;
            BsonValue divisor;
            BsonValue remainder;

            if (divisorExpression.Type == typeof(decimal) && remainderExpression.Type == typeof(decimal))
            {
                divisor   = divisorExpression.GetConstantValue <decimal>(containingExpression: moduloExpression);
                remainder = remainderExpression.GetConstantValue <decimal>(containingExpression: expression);
            }
            else if (divisorExpression.Type == typeof(double) && remainderExpression.Type == typeof(double))
            {
                divisor   = divisorExpression.GetConstantValue <double>(containingExpression: moduloExpression);
                remainder = remainderExpression.GetConstantValue <double>(containingExpression: expression);
            }
            else if (divisorExpression.Type == typeof(float) && remainderExpression.Type == typeof(float))
            {
                divisor   = divisorExpression.GetConstantValue <float>(containingExpression: moduloExpression);
                remainder = remainderExpression.GetConstantValue <float>(containingExpression: expression);
            }
            else if (divisorExpression.Type == typeof(int) && remainderExpression.Type == typeof(int))
            {
                divisor   = divisorExpression.GetConstantValue <int>(containingExpression: moduloExpression);
                remainder = remainderExpression.GetConstantValue <int>(containingExpression: expression);
            }
            else if (divisorExpression.Type == typeof(long) && remainderExpression.Type == typeof(long))
            {
                divisor   = divisorExpression.GetConstantValue <long>(containingExpression: moduloExpression);
                remainder = remainderExpression.GetConstantValue <long>(containingExpression: expression);
            }
            else if (divisorExpression.Type == typeof(uint) && remainderExpression.Type == typeof(uint))
            {
                divisor   = divisorExpression.GetConstantValue <uint>(containingExpression: moduloExpression);
                remainder = remainderExpression.GetConstantValue <uint>(containingExpression: expression);
            }
            else if (divisorExpression.Type == typeof(ulong) && remainderExpression.Type == typeof(ulong))
            {
                divisor   = (long)divisorExpression.GetConstantValue <ulong>(containingExpression: moduloExpression);
                remainder = (long)remainderExpression.GetConstantValue <ulong>(containingExpression: expression);
            }
            else
            {
                throw new ExpressionNotSupportedException(expression);
            }

            var moduloComparisonAst = AstFilter.Mod(field, divisor, remainder);

            switch (expression.NodeType)
            {
            case ExpressionType.Equal:
                return(moduloComparisonAst);

            case ExpressionType.NotEqual:
                return(AstFilter.Not(moduloComparisonAst));
            }

            throw new ExpressionNotSupportedException(expression);
        }