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));
// 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); }
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); }
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); }
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); }
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); }
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); }
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)); }
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); }