diff --git a/src/MongoDB.Bson/Serialization/IBsonNumericSerializer.cs b/src/MongoDB.Bson/Serialization/IBsonNumericSerializer.cs deleted file mode 100644 index 12019f27e61..00000000000 --- a/src/MongoDB.Bson/Serialization/IBsonNumericSerializer.cs +++ /dev/null @@ -1,35 +0,0 @@ -/* Copyright 2010-present MongoDB Inc. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -using MongoDB.Bson.Serialization.Options; - -namespace MongoDB.Bson.Serialization -{ - /// - /// Implemented by serializers that serialize numeric values. - /// - public interface IBsonNumericSerializer - { - /// - /// Gets the representation converter. - /// - RepresentationConverter Converter { get; } - - /// - /// Gets the representation. - /// - BsonType Representation { get; } - } -} diff --git a/src/MongoDB.Bson/Serialization/Options/RepresentationConverter.cs b/src/MongoDB.Bson/Serialization/Options/RepresentationConverter.cs index 79179cde5e5..801dc2b604e 100644 --- a/src/MongoDB.Bson/Serialization/Options/RepresentationConverter.cs +++ b/src/MongoDB.Bson/Serialization/Options/RepresentationConverter.cs @@ -14,6 +14,7 @@ */ using System; +using MongoDB.Bson.Serialization.Attributes; namespace MongoDB.Bson.Serialization.Options { @@ -56,70 +57,6 @@ public bool AllowTruncation } // public methods - /// - /// Converts an Int32 to a byte. - /// - /// An Int32. - /// A byte. - public byte ToByte(int value) - { - if (value < byte.MinValue || value > byte.MaxValue) - { - if (!_allowOverflow) { throw new OverflowException(); } - return unchecked((byte)value); - } - - return checked((byte)value); - } - - /// - /// Converts an Int64 to a byte. - /// - /// An Int64. - /// A byte. - public byte ToByte(long value) - { - if (value < byte.MinValue || value > byte.MaxValue) - { - if (!_allowOverflow) { throw new OverflowException(); } - return unchecked((byte)value); - } - - return checked((byte)value); - } - - /// - /// Converts an Int32 to a char. - /// - /// An Int32. - /// A char. - public char ToChar(int value) - { - if (value < char.MinValue || value > char.MaxValue) - { - if (!_allowOverflow) { throw new OverflowException(); } - return unchecked((char)value); - } - - return checked((char)value); - } - - /// - /// Converts an Int64 to a char. - /// - /// An Int64. - /// A char. - public char ToChar(long value) - { - if (value < char.MinValue || value > char.MaxValue) - { - if (!_allowOverflow) { throw new OverflowException(); } - return unchecked((char)value); - } - - return checked((char)value); - } - /// /// Converts a Decimal128 to a Decimal. /// @@ -548,26 +485,6 @@ public short ToInt16(long value) return (short)value; } - /// - /// Converts a byte to an Int32. - /// - /// A byte. - /// An Int32. - public int ToInt32(byte value) - { - return (int)value; - } - - /// - /// Converts a char to an Int32. - /// - /// A char. - /// An Int32. - public int ToInt32(char value) - { - return (int)value; - } - /// /// Converts a Decimal to an Int32. /// @@ -681,17 +598,6 @@ public int ToInt32(long value) return (int)value; } - /// - /// Converts an sbyte to an Int32. - /// - /// An sbyte. - /// An Int32. - [CLSCompliant(false)] - public int ToInt32(sbyte value) - { - return (int)value; - } - /// /// Converts an Int16 to an Int32. /// @@ -743,26 +649,6 @@ public int ToInt32(ushort value) return value; } - /// - /// Converts a byte to an Int64. - /// - /// A byte. - /// An Int64. - public long ToInt64(byte value) - { - return (long)value; - } - - /// - /// Converts a char to an Int64. - /// - /// A char. - /// An Int64. - public long ToInt64(char value) - { - return (long)value; - } - /// /// Converts a Decimal to an Int64. /// @@ -872,17 +758,6 @@ public long ToInt64(long value) return value; } - /// - /// Converts an sbyte to an Int64. - /// - /// An sbyte. - /// An Int64. - [CLSCompliant(false)] - public long ToInt64(sbyte value) - { - return (long)value; - } - /// /// Converts an Int16 to an Int64. /// @@ -930,40 +805,6 @@ public long ToInt64(ushort value) return value; } - /// - /// Converts an Int32 to an sbyte. - /// - /// An Int32. - /// An sbyte. - [CLSCompliant(false)] - public sbyte ToSByte(int value) - { - if (value < sbyte.MinValue || value > sbyte.MaxValue) - { - if (!_allowOverflow) { throw new OverflowException(); } - return unchecked((sbyte)value); - } - - return checked((sbyte)value); - } - - /// - /// Converts an Int64 to an sbyte. - /// - /// An Int64. - /// An sbyte. - [CLSCompliant(false)] - public sbyte ToSByte(long value) - { - if (value < sbyte.MinValue || value > sbyte.MaxValue) - { - if (!_allowOverflow) { throw new OverflowException(); } - return unchecked((sbyte)value); - } - - return checked((sbyte)value); - } - /// /// Converts a Decimal128 to a Single. /// diff --git a/src/MongoDB.Bson/Serialization/Serializers/ByteSerializer.cs b/src/MongoDB.Bson/Serialization/Serializers/ByteSerializer.cs index a515619c4f4..aba46107f76 100644 --- a/src/MongoDB.Bson/Serialization/Serializers/ByteSerializer.cs +++ b/src/MongoDB.Bson/Serialization/Serializers/ByteSerializer.cs @@ -15,6 +15,9 @@ using System; using System.Globalization; +using System.IO; +using MongoDB.Bson.IO; +using MongoDB.Bson.Serialization.Attributes; using MongoDB.Bson.Serialization.Options; namespace MongoDB.Bson.Serialization.Serializers @@ -22,14 +25,10 @@ namespace MongoDB.Bson.Serialization.Serializers /// /// Represents a serializer for Bytes. /// - public class ByteSerializer : StructSerializerBase, - IRepresentationConfigurable, - IRepresentationConverterConfigurable, - IBsonNumericSerializer + public class ByteSerializer : StructSerializerBase, IRepresentationConfigurable { // private fields private readonly BsonType _representation; - private readonly RepresentationConverter _converter; // constructors /// @@ -45,16 +44,6 @@ public ByteSerializer() /// /// The representation. public ByteSerializer(BsonType representation) - : this(representation, new RepresentationConverter(false, false)) - { - } - - /// - /// Initializes a new instance of the class. - /// - /// The representation. - /// The converter. - public ByteSerializer(BsonType representation, RepresentationConverter converter) { switch (representation) { @@ -70,21 +59,9 @@ public ByteSerializer(BsonType representation, RepresentationConverter converter } _representation = representation; - _converter = converter; } // public properties - /// - /// Gets the converter. - /// - /// - /// The converter. - /// - public RepresentationConverter Converter - { - get { return _converter; } - } - /// /// Gets the representation. /// @@ -106,6 +83,8 @@ public BsonType Representation public override byte Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args) { var bsonReader = context.Reader; + byte value; + var lostData = false; var bsonType = bsonReader.GetCurrentBsonType(); switch (bsonType) @@ -116,13 +95,20 @@ public override byte Deserialize(BsonDeserializationContext context, BsonDeseria { throw new FormatException("Binary data for Byte must be exactly one byte long."); } - return bytes[0]; + value = bytes[0]; + break; case BsonType.Int32: - return _converter.ToByte(bsonReader.ReadInt32()); + var int32Value = bsonReader.ReadInt32(); + value = (byte)int32Value; + lostData = (int)value != int32Value; + break; case BsonType.Int64: - return _converter.ToByte(bsonReader.ReadInt64()); + var int64Value = bsonReader.ReadInt64(); + value = (byte)int64Value; + lostData = (int)value != int64Value; + break; case BsonType.String: var s = bsonReader.ReadString(); @@ -130,11 +116,20 @@ public override byte Deserialize(BsonDeserializationContext context, BsonDeseria { s = "0" + s; } - return byte.Parse(s, NumberStyles.HexNumber); + value = byte.Parse(s, NumberStyles.HexNumber); + break; default: throw CreateCannotDeserializeFromBsonTypeException(bsonType); } + + if (lostData) + { + var message = string.Format("Data loss occurred when trying to convert from {0} to Byte.", bsonType); + throw new FormatException(message); + } + + return value; } /// @@ -154,11 +149,11 @@ public override void Serialize(BsonSerializationContext context, BsonSerializati break; case BsonType.Int32: - bsonWriter.WriteInt32(_converter.ToInt32(value)); + bsonWriter.WriteInt32(value); break; case BsonType.Int64: - bsonWriter.WriteInt64(_converter.ToInt64(value)); + bsonWriter.WriteInt64(value); break; case BsonType.String: @@ -171,23 +166,6 @@ public override void Serialize(BsonSerializationContext context, BsonSerializati } } - /// - /// Returns a serializer that has been reconfigured with the specified item serializer. - /// - /// The converter. - /// The reconfigured serializer. - public ByteSerializer WithConverter(RepresentationConverter converter) - { - if (converter == _converter) - { - return this; - } - else - { - return new ByteSerializer(_representation, converter); - } - } - /// /// Returns a serializer that has been reconfigured with the specified representation. /// @@ -201,16 +179,11 @@ public ByteSerializer WithRepresentation(BsonType representation) } else { - return new ByteSerializer(representation, _converter); + return new ByteSerializer(representation); } } // explicit interface implementations - IBsonSerializer IRepresentationConverterConfigurable.WithConverter(RepresentationConverter converter) - { - return WithConverter(converter); - } - IBsonSerializer IRepresentationConfigurable.WithRepresentation(BsonType representation) { return WithRepresentation(representation); diff --git a/src/MongoDB.Bson/Serialization/Serializers/CharSerializer.cs b/src/MongoDB.Bson/Serialization/Serializers/CharSerializer.cs index e25f4191da9..fef5ad10f8c 100644 --- a/src/MongoDB.Bson/Serialization/Serializers/CharSerializer.cs +++ b/src/MongoDB.Bson/Serialization/Serializers/CharSerializer.cs @@ -14,6 +14,9 @@ */ using System; +using System.IO; +using MongoDB.Bson.IO; +using MongoDB.Bson.Serialization.Attributes; using MongoDB.Bson.Serialization.Options; namespace MongoDB.Bson.Serialization.Serializers @@ -21,14 +24,10 @@ namespace MongoDB.Bson.Serialization.Serializers /// /// Represents a serializer for Chars. /// - public class CharSerializer : StructSerializerBase, - IRepresentationConfigurable, - IRepresentationConverterConfigurable, - IBsonNumericSerializer + public class CharSerializer : StructSerializerBase, IRepresentationConfigurable { // private fields private readonly BsonType _representation; - private readonly RepresentationConverter _converter; // constructors /// @@ -44,16 +43,6 @@ public CharSerializer() /// /// The representation. public CharSerializer(BsonType representation) - : this(representation, new RepresentationConverter(false, false)) - { - } - - /// - /// Initializes a new instance of the class. - /// - /// The representation. - /// The converter. - public CharSerializer(BsonType representation, RepresentationConverter converter) { switch (representation) { @@ -68,21 +57,9 @@ public CharSerializer(BsonType representation, RepresentationConverter converter } _representation = representation; - _converter = converter; } // public properties - /// - /// Gets the converter. - /// - /// - /// The converter. - /// - public RepresentationConverter Converter - { - get { return _converter; } - } - /// /// Gets the representation. /// @@ -109,10 +86,10 @@ public override char Deserialize(BsonDeserializationContext context, BsonDeseria switch (bsonType) { case BsonType.Int32: - return _converter.ToChar(bsonReader.ReadInt32()); + return (char)bsonReader.ReadInt32(); case BsonType.Int64: - return _converter.ToChar(bsonReader.ReadInt64()); + return (char)bsonReader.ReadInt64(); case BsonType.String: return (char)bsonReader.ReadString()[0]; @@ -135,11 +112,11 @@ public override void Serialize(BsonSerializationContext context, BsonSerializati switch (_representation) { case BsonType.Int32: - bsonWriter.WriteInt32(_converter.ToInt32(value)); + bsonWriter.WriteInt32((int)value); break; case BsonType.Int64: - bsonWriter.WriteInt64(_converter.ToInt64(value)); + bsonWriter.WriteInt64((int)value); break; case BsonType.String: @@ -152,23 +129,6 @@ public override void Serialize(BsonSerializationContext context, BsonSerializati } } - /// - /// Returns a serializer that has been reconfigured with the specified converter. - /// - /// The converter. - /// The reconfigured serializer. - public CharSerializer WithConverter(RepresentationConverter converter) - { - if (converter == _converter) - { - return this; - } - else - { - return new CharSerializer(_representation, converter); - } - } - /// /// Returns a serializer that has been reconfigured with the specified representation. /// @@ -182,16 +142,11 @@ public CharSerializer WithRepresentation(BsonType representation) } else { - return new CharSerializer(representation, _converter); + return new CharSerializer(representation); } } // explicit interface implementations - IBsonSerializer IRepresentationConverterConfigurable.WithConverter(RepresentationConverter converter) - { - return WithConverter(converter); - } - IBsonSerializer IRepresentationConfigurable.WithRepresentation(BsonType representation) { return WithRepresentation(representation); diff --git a/src/MongoDB.Bson/Serialization/Serializers/Decimal128Serializer.cs b/src/MongoDB.Bson/Serialization/Serializers/Decimal128Serializer.cs index 553fd54e9a8..497e7a06a62 100644 --- a/src/MongoDB.Bson/Serialization/Serializers/Decimal128Serializer.cs +++ b/src/MongoDB.Bson/Serialization/Serializers/Decimal128Serializer.cs @@ -22,10 +22,7 @@ namespace MongoDB.Bson.Serialization.Serializers /// /// Represents a serializer for Decimal128s. /// - public class Decimal128Serializer : StructSerializerBase, - IRepresentationConfigurable, - IRepresentationConverterConfigurable, - IBsonNumericSerializer + public class Decimal128Serializer : StructSerializerBase, IRepresentationConfigurable, IRepresentationConverterConfigurable { #region static private static readonly Decimal128Serializer __decimal128Instance = new Decimal128Serializer(BsonType.Decimal128); diff --git a/src/MongoDB.Bson/Serialization/Serializers/DecimalSerializer.cs b/src/MongoDB.Bson/Serialization/Serializers/DecimalSerializer.cs index e79553d00e6..c4a8b69ba11 100644 --- a/src/MongoDB.Bson/Serialization/Serializers/DecimalSerializer.cs +++ b/src/MongoDB.Bson/Serialization/Serializers/DecimalSerializer.cs @@ -22,10 +22,7 @@ namespace MongoDB.Bson.Serialization.Serializers /// /// Represents a serializer for Decimals. /// - public class DecimalSerializer : StructSerializerBase, - IRepresentationConfigurable, - IRepresentationConverterConfigurable, - IBsonNumericSerializer + public class DecimalSerializer : StructSerializerBase, IRepresentationConfigurable, IRepresentationConverterConfigurable { #region static private static readonly DecimalSerializer __decimal128Instance = new DecimalSerializer(BsonType.Decimal128); diff --git a/src/MongoDB.Bson/Serialization/Serializers/DoubleSerializer.cs b/src/MongoDB.Bson/Serialization/Serializers/DoubleSerializer.cs index ea0eaddbdd7..b078c8ab45d 100644 --- a/src/MongoDB.Bson/Serialization/Serializers/DoubleSerializer.cs +++ b/src/MongoDB.Bson/Serialization/Serializers/DoubleSerializer.cs @@ -22,10 +22,7 @@ namespace MongoDB.Bson.Serialization.Serializers /// /// Represents a serializer for Doubles. /// - public class DoubleSerializer : StructSerializerBase, - IRepresentationConfigurable, - IRepresentationConverterConfigurable, - IBsonNumericSerializer + public class DoubleSerializer : StructSerializerBase, IRepresentationConfigurable, IRepresentationConverterConfigurable { #region static private static readonly DoubleSerializer __instance = new DoubleSerializer(); diff --git a/src/MongoDB.Bson/Serialization/Serializers/Int16Serializer.cs b/src/MongoDB.Bson/Serialization/Serializers/Int16Serializer.cs index fef176beb6b..b81a77da546 100644 --- a/src/MongoDB.Bson/Serialization/Serializers/Int16Serializer.cs +++ b/src/MongoDB.Bson/Serialization/Serializers/Int16Serializer.cs @@ -14,7 +14,9 @@ */ using System; +using System.IO; using MongoDB.Bson.IO; +using MongoDB.Bson.Serialization.Attributes; using MongoDB.Bson.Serialization.Options; namespace MongoDB.Bson.Serialization.Serializers @@ -22,10 +24,7 @@ namespace MongoDB.Bson.Serialization.Serializers /// /// Represents a serializer for Int16s. /// - public class Int16Serializer : StructSerializerBase, - IRepresentationConfigurable, - IRepresentationConverterConfigurable, - IBsonNumericSerializer + public class Int16Serializer : StructSerializerBase, IRepresentationConfigurable, IRepresentationConverterConfigurable { // private fields private readonly BsonType _representation; diff --git a/src/MongoDB.Bson/Serialization/Serializers/Int32Serializer.cs b/src/MongoDB.Bson/Serialization/Serializers/Int32Serializer.cs index 6554337a13c..ee6a23c2d86 100644 --- a/src/MongoDB.Bson/Serialization/Serializers/Int32Serializer.cs +++ b/src/MongoDB.Bson/Serialization/Serializers/Int32Serializer.cs @@ -22,10 +22,7 @@ namespace MongoDB.Bson.Serialization.Serializers /// /// Represents a serializer for Int32. /// - public class Int32Serializer : StructSerializerBase, - IRepresentationConfigurable, - IRepresentationConverterConfigurable, - IBsonNumericSerializer + public class Int32Serializer : StructSerializerBase, IRepresentationConfigurable, IRepresentationConverterConfigurable { #region static private static readonly Int32Serializer __instance = new Int32Serializer(); diff --git a/src/MongoDB.Bson/Serialization/Serializers/Int64Serializer.cs b/src/MongoDB.Bson/Serialization/Serializers/Int64Serializer.cs index 4c5750764b0..96674fb18c3 100644 --- a/src/MongoDB.Bson/Serialization/Serializers/Int64Serializer.cs +++ b/src/MongoDB.Bson/Serialization/Serializers/Int64Serializer.cs @@ -22,10 +22,7 @@ namespace MongoDB.Bson.Serialization.Serializers /// /// Represents a serializer for Int64s. /// - public class Int64Serializer : StructSerializerBase, - IRepresentationConfigurable, - IRepresentationConverterConfigurable, - IBsonNumericSerializer + public class Int64Serializer : StructSerializerBase, IRepresentationConfigurable, IRepresentationConverterConfigurable { #region static private static readonly Int64Serializer __instance = new Int64Serializer(); diff --git a/src/MongoDB.Bson/Serialization/Serializers/SByteSerializer.cs b/src/MongoDB.Bson/Serialization/Serializers/SByteSerializer.cs index e17b075f767..bd6c7074307 100644 --- a/src/MongoDB.Bson/Serialization/Serializers/SByteSerializer.cs +++ b/src/MongoDB.Bson/Serialization/Serializers/SByteSerializer.cs @@ -15,6 +15,9 @@ using System; using System.Globalization; +using System.IO; +using MongoDB.Bson.IO; +using MongoDB.Bson.Serialization.Attributes; using MongoDB.Bson.Serialization.Options; namespace MongoDB.Bson.Serialization.Serializers @@ -23,14 +26,10 @@ namespace MongoDB.Bson.Serialization.Serializers /// Represents a serializer for SBytes. /// [CLSCompliant(false)] - public class SByteSerializer : StructSerializerBase, - IRepresentationConfigurable, - IRepresentationConverterConfigurable, - IBsonNumericSerializer + public class SByteSerializer : StructSerializerBase, IRepresentationConfigurable { // private fields private readonly BsonType _representation; - private readonly RepresentationConverter _converter; // constructors /// @@ -46,16 +45,6 @@ public SByteSerializer() /// /// The representation. public SByteSerializer(BsonType representation) - : this(representation, new RepresentationConverter(false, false)) - { - } - - /// - /// Initializes a new instance of the class. - /// - /// The representation. - /// The converter. - public SByteSerializer(BsonType representation, RepresentationConverter converter) { switch (representation) { @@ -71,16 +60,9 @@ public SByteSerializer(BsonType representation, RepresentationConverter converte } _representation = representation; - _converter = converter; } // public properties - /// - public RepresentationConverter Converter - { - get { return _converter; } - } - /// /// Gets the representation. /// @@ -102,6 +84,8 @@ public BsonType Representation public override sbyte Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args) { var bsonReader = context.Reader; + sbyte value; + var lostData = false; var bsonType = bsonReader.GetCurrentBsonType(); switch (bsonType) @@ -112,13 +96,20 @@ public override sbyte Deserialize(BsonDeserializationContext context, BsonDeseri { throw new FormatException("Binary data for SByte must be exactly one byte long."); } - return (sbyte)bytes[0]; + value = (sbyte)bytes[0]; + break; case BsonType.Int32: - return _converter.ToSByte(bsonReader.ReadInt32()); + var int32Value = bsonReader.ReadInt32(); + value = (sbyte)int32Value; + lostData = (int)value != int32Value; + break; case BsonType.Int64: - return _converter.ToSByte(bsonReader.ReadInt64()); + var int64Value = bsonReader.ReadInt64(); + value = (sbyte)int64Value; + lostData = (int)value != int64Value; + break; case BsonType.String: var s = bsonReader.ReadString(); @@ -126,11 +117,20 @@ public override sbyte Deserialize(BsonDeserializationContext context, BsonDeseri { s = "0" + s; } - return (sbyte)byte.Parse(s, NumberStyles.HexNumber); + value = (sbyte)byte.Parse(s, NumberStyles.HexNumber); + break; default: throw CreateCannotDeserializeFromBsonTypeException(bsonType); } + + if (lostData) + { + var message = string.Format("Data loss occurred when trying to convert from {0} to SByte.", bsonType); + throw new FormatException(message); + } + + return value; } /// @@ -150,11 +150,11 @@ public override void Serialize(BsonSerializationContext context, BsonSerializati break; case BsonType.Int32: - bsonWriter.WriteInt32(_converter.ToInt32(value)); + bsonWriter.WriteInt32(value); break; case BsonType.Int64: - bsonWriter.WriteInt64(_converter.ToInt64(value)); + bsonWriter.WriteInt64(value); break; case BsonType.String: @@ -167,23 +167,6 @@ public override void Serialize(BsonSerializationContext context, BsonSerializati } } - /// - /// Returns a serializer that has been reconfigured with the specified converter. - /// - /// The converter. - /// The reconfigured serializer. - public SByteSerializer WithConverter(RepresentationConverter converter) - { - if (converter == _converter) - { - return this; - } - else - { - return new SByteSerializer(_representation, converter); - } - } - /// /// Returns a serializer that has been reconfigured with the specified representation. /// @@ -197,16 +180,11 @@ public SByteSerializer WithRepresentation(BsonType representation) } else { - return new SByteSerializer(representation, _converter); + return new SByteSerializer(representation); } } // explicit interface implementations - IBsonSerializer IRepresentationConverterConfigurable.WithConverter(RepresentationConverter converter) - { - return WithConverter(converter); - } - IBsonSerializer IRepresentationConfigurable.WithRepresentation(BsonType representation) { return WithRepresentation(representation); diff --git a/src/MongoDB.Bson/Serialization/Serializers/UInt16Serializer.cs b/src/MongoDB.Bson/Serialization/Serializers/UInt16Serializer.cs index 7626cb06d77..5445b7d72cb 100644 --- a/src/MongoDB.Bson/Serialization/Serializers/UInt16Serializer.cs +++ b/src/MongoDB.Bson/Serialization/Serializers/UInt16Serializer.cs @@ -14,7 +14,9 @@ */ using System; +using System.IO; using MongoDB.Bson.IO; +using MongoDB.Bson.Serialization.Attributes; using MongoDB.Bson.Serialization.Options; namespace MongoDB.Bson.Serialization.Serializers @@ -23,10 +25,7 @@ namespace MongoDB.Bson.Serialization.Serializers /// Represents a serializer for UInt16s. /// [CLSCompliant(false)] - public class UInt16Serializer : StructSerializerBase, - IRepresentationConfigurable, - IRepresentationConverterConfigurable, - IBsonNumericSerializer + public class UInt16Serializer : StructSerializerBase, IRepresentationConfigurable, IRepresentationConverterConfigurable { // private fields private readonly BsonType _representation; diff --git a/src/MongoDB.Bson/Serialization/Serializers/UInt32Serializer.cs b/src/MongoDB.Bson/Serialization/Serializers/UInt32Serializer.cs index fbad434ab7e..e87ca334887 100644 --- a/src/MongoDB.Bson/Serialization/Serializers/UInt32Serializer.cs +++ b/src/MongoDB.Bson/Serialization/Serializers/UInt32Serializer.cs @@ -14,7 +14,9 @@ */ using System; +using System.IO; using MongoDB.Bson.IO; +using MongoDB.Bson.Serialization.Attributes; using MongoDB.Bson.Serialization.Options; namespace MongoDB.Bson.Serialization.Serializers @@ -23,10 +25,7 @@ namespace MongoDB.Bson.Serialization.Serializers /// Represents a serializer for UInt32s. /// [CLSCompliant(false)] - public class UInt32Serializer : StructSerializerBase, - IRepresentationConfigurable, - IRepresentationConverterConfigurable, - IBsonNumericSerializer + public class UInt32Serializer : StructSerializerBase, IRepresentationConfigurable, IRepresentationConverterConfigurable { // private fields private readonly BsonType _representation; diff --git a/src/MongoDB.Bson/Serialization/Serializers/UInt64Serializer.cs b/src/MongoDB.Bson/Serialization/Serializers/UInt64Serializer.cs index 8380734ccaa..a3f3e4a8cd0 100644 --- a/src/MongoDB.Bson/Serialization/Serializers/UInt64Serializer.cs +++ b/src/MongoDB.Bson/Serialization/Serializers/UInt64Serializer.cs @@ -14,7 +14,9 @@ */ using System; +using System.IO; using MongoDB.Bson.IO; +using MongoDB.Bson.Serialization.Attributes; using MongoDB.Bson.Serialization.Options; namespace MongoDB.Bson.Serialization.Serializers @@ -23,10 +25,7 @@ namespace MongoDB.Bson.Serialization.Serializers /// Represents a serializer for UInt64s. /// [CLSCompliant(false)] - public class UInt64Serializer : StructSerializerBase, - IRepresentationConfigurable, - IRepresentationConverterConfigurable, - IBsonNumericSerializer + public class UInt64Serializer : StructSerializerBase, IRepresentationConfigurable, IRepresentationConverterConfigurable { // private fields private readonly BsonType _representation; diff --git a/src/MongoDB.Driver/Linq/Linq3Implementation/Misc/ConvertHelper.cs b/src/MongoDB.Driver/Linq/Linq3Implementation/Misc/ConvertHelper.cs index f1889226f51..6cfec336a72 100644 --- a/src/MongoDB.Driver/Linq/Linq3Implementation/Misc/ConvertHelper.cs +++ b/src/MongoDB.Driver/Linq/Linq3Implementation/Misc/ConvertHelper.cs @@ -41,12 +41,6 @@ private readonly static (Type SourceType, Type TargetType)[] __wideningConverts (typeof(sbyte), typeof(float)), (typeof(sbyte), typeof(double)), (typeof(sbyte), typeof(decimal)), - (typeof(char), typeof(short)), - (typeof(char), typeof(ushort)), - (typeof(char), typeof(int)), - (typeof(char), typeof(uint)), - (typeof(char), typeof(long)), - (typeof(char), typeof(ulong)), (typeof(short), typeof(int)), (typeof(short), typeof(uint)), (typeof(short), typeof(long)), @@ -77,14 +71,11 @@ private readonly static (Type SourceType, Type TargetType)[] __wideningConverts (typeof(ulong), typeof(float)), (typeof(ulong), typeof(double)), (typeof(ulong), typeof(decimal)), - (typeof(float), typeof(double)) + (typeof(float), typeof(double)), + (typeof(float), typeof(decimal)), + (typeof(double), typeof(decimal)) }; - public static bool IsWideningConvert(Type sourceType, Type targetType) - { - return __wideningConverts.Contains((sourceType, targetType)); - } - public static Expression RemoveConvertToMongoQueryable(Expression expression) { if (expression.NodeType == ExpressionType.Convert) @@ -163,6 +154,11 @@ public static Expression RemoveWideningConvert(Expression expression) } return expression; + + static bool IsWideningConvert(Type sourceType, Type targetType) + { + return __wideningConverts.Contains((sourceType, targetType)); + } } } } diff --git a/src/MongoDB.Driver/Linq/Linq3Implementation/Misc/SerializationHelper.cs b/src/MongoDB.Driver/Linq/Linq3Implementation/Misc/SerializationHelper.cs index c9d938c106b..346a6f688a5 100644 --- a/src/MongoDB.Driver/Linq/Linq3Implementation/Misc/SerializationHelper.cs +++ b/src/MongoDB.Driver/Linq/Linq3Implementation/Misc/SerializationHelper.cs @@ -53,27 +53,19 @@ static bool IsNumericRepresentation(BsonType representation) public static BsonValue SerializeValue(IBsonSerializer serializer, ConstantExpression constantExpression, Expression containingExpression) { var value = constantExpression.Value; - - try + if (value == null || serializer.ValueType.IsAssignableFrom(value.GetType())) { - if (value == null || serializer.ValueType.IsAssignableFrom(value.GetType())) - { - return SerializeValue(serializer, value); - } - - if (value.GetType().ImplementsIEnumerable(out var itemType) && - serializer is IBsonArraySerializer arraySerializer && - arraySerializer.TryGetItemSerializationInfo(out var itemSerializationInfo) && - itemSerializationInfo.Serializer is var itemSerializer && - itemSerializer.ValueType.IsAssignableFrom(itemType)) - { - var ienumerableSerializer = IEnumerableSerializer.Create(itemSerializer); - return SerializeValue(ienumerableSerializer, value); - } + return SerializeValue(serializer, value); } - catch (Exception ex) + + if (value.GetType().ImplementsIEnumerable(out var itemType) && + serializer is IBsonArraySerializer arraySerializer && + arraySerializer.TryGetItemSerializationInfo(out var itemSerializationInfo) && + itemSerializationInfo.Serializer is var itemSerializer && + itemSerializer.ValueType.IsAssignableFrom(itemType)) { - throw new ExpressionNotSupportedException(constantExpression, containingExpression, because: ex.Message.TrimEnd('.')); + var ienumerableSerializer = IEnumerableSerializer.Create(itemSerializer); + return SerializeValue(ienumerableSerializer, value); } throw new ExpressionNotSupportedException(constantExpression, containingExpression, because: "it was not possible to determine how to serialize the constant"); diff --git a/src/MongoDB.Driver/Linq/Linq3Implementation/Serializers/ConvertingNumericSerializer.cs b/src/MongoDB.Driver/Linq/Linq3Implementation/Serializers/ConvertingNumericSerializer.cs deleted file mode 100644 index 8be4ca1f403..00000000000 --- a/src/MongoDB.Driver/Linq/Linq3Implementation/Serializers/ConvertingNumericSerializer.cs +++ /dev/null @@ -1,218 +0,0 @@ -/* Copyright 2010-present MongoDB Inc. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -using System; -using MongoDB.Bson; -using MongoDB.Bson.Serialization; -using MongoDB.Bson.Serialization.Serializers; - -namespace MongoDB.Driver.Linq.Linq3Implementation.Serializers -{ - internal static class ConvertingNumericSerializer - { - public static IBsonSerializer Create( - Type sourceType, - Type targetType, - IBsonSerializer sourceSerializer) - { - var numericConversionSerializerType = typeof(ConvertingNumericSerializer<,>).MakeGenericType(sourceType, targetType); - return (IBsonSerializer)Activator.CreateInstance(numericConversionSerializerType, sourceSerializer); - } - } - - internal class ConvertingNumericSerializer : SerializerBase - { - private readonly IBsonSerializer _sourceSerializer; - - public ConvertingNumericSerializer(IBsonSerializer sourceSerializer) - { - _sourceSerializer = sourceSerializer ?? throw new ArgumentNullException(nameof(sourceSerializer)); - } - - public override TTarget Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args) - { - var sourceValue = _sourceSerializer.Deserialize(context, args); - return ConvertChecked(sourceValue); - } - - public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, TTarget value) - { - var sourceValue = ConvertChecked(value); - _sourceSerializer.Serialize(context, args, sourceValue); - } - - private TTo ConvertChecked(TFrom value) - { - var fromTypeCode = Type.GetTypeCode(typeof(TFrom)); - var toTypeCode = Type.GetTypeCode(typeof(TTo)); - - var converted = (TTo)ConvertUnchecked(fromTypeCode, toTypeCode, value); - var convertedBack = ConvertUnchecked(toTypeCode, fromTypeCode, converted); - if (convertedBack.Equals(value)) - { - return converted; - } - - throw new BsonSerializationException($"The constant {value} could not be converted to {GetTypeCodeName(toTypeCode)} in order to be serialized using the proper serializer."); - } - - private object ConvertUnchecked(TypeCode fromTypeCode, TypeCode toTypeCode, object value) - { - unchecked - { - return (fromTypeCode, toTypeCode) switch - { - (TypeCode.Byte, TypeCode.Char) => (char)(byte)value, - (TypeCode.Byte, TypeCode.Decimal) => (decimal)(byte)value, - (TypeCode.Byte, TypeCode.Double) => (double)(byte)value, - (TypeCode.Byte, TypeCode.Int16) => (short)(byte)value, - (TypeCode.Byte, TypeCode.Int32) => (int)(byte)value, - (TypeCode.Byte, TypeCode.Int64) => (long)(byte)value, - (TypeCode.Byte, TypeCode.SByte) => (sbyte)(byte)value, - (TypeCode.Byte, TypeCode.Single) => (float)(byte)value, - (TypeCode.Byte, TypeCode.UInt16) => (ushort)(byte)value, - (TypeCode.Byte, TypeCode.UInt32) => (uint)(byte)value, - (TypeCode.Byte, TypeCode.UInt64) => (ulong)(byte)value, - (TypeCode.Char, TypeCode.Byte) => (byte)(char)value, - (TypeCode.Char, TypeCode.Decimal) => (decimal)(char)value, - (TypeCode.Char, TypeCode.Double) => (double)(char)value, - (TypeCode.Char, TypeCode.Int16) => (short)(char)value, - (TypeCode.Char, TypeCode.Int32) => (int)(char)value, - (TypeCode.Char, TypeCode.Int64) => (long)(char)value, - (TypeCode.Char, TypeCode.SByte) => (sbyte)(char)value, - (TypeCode.Char, TypeCode.Single) => (float)(char)value, - (TypeCode.Char, TypeCode.UInt16) => (ushort)(char)value, - (TypeCode.Char, TypeCode.UInt32) => (uint)(char)value, - (TypeCode.Char, TypeCode.UInt64) => (ulong)(char)value, - (TypeCode.Decimal, TypeCode.Byte) => (byte)(decimal)value, - (TypeCode.Decimal, TypeCode.Char) => (char)(decimal)value, - (TypeCode.Decimal, TypeCode.Double) => (double)(decimal)value, - (TypeCode.Decimal, TypeCode.Int16) => (short)(decimal)value, - (TypeCode.Decimal, TypeCode.Int32) => (int)(decimal)value, - (TypeCode.Decimal, TypeCode.Int64) => (long)(decimal)value, - (TypeCode.Decimal, TypeCode.SByte) => (sbyte)(decimal)value, - (TypeCode.Decimal, TypeCode.Single) => (float)(decimal)value, - (TypeCode.Decimal, TypeCode.UInt16) => (ushort)(decimal)value, - (TypeCode.Decimal, TypeCode.UInt32) => (uint)(decimal)value, - (TypeCode.Decimal, TypeCode.UInt64) => (ulong)(decimal)value, - (TypeCode.Double, TypeCode.Byte) => (byte)(double)value, - (TypeCode.Double, TypeCode.Char) => (char)(double)value, - (TypeCode.Double, TypeCode.Decimal) => (decimal)(double)value, - (TypeCode.Double, TypeCode.Int16) => (short)(double)value, - (TypeCode.Double, TypeCode.Int32) => (int)(double)value, - (TypeCode.Double, TypeCode.Int64) => (long)(double)value, - (TypeCode.Double, TypeCode.SByte) => (sbyte)(double)value, - (TypeCode.Double, TypeCode.Single) => (float)(double)value, - (TypeCode.Double, TypeCode.UInt16) => (ushort)(double)value, - (TypeCode.Double, TypeCode.UInt32) => (uint)(double)value, - (TypeCode.Double, TypeCode.UInt64) => (ulong)(double)value, - (TypeCode.Int16, TypeCode.Byte) => (byte)(short)value, - (TypeCode.Int16, TypeCode.Char) => (char)(short)value, - (TypeCode.Int16, TypeCode.Decimal) => (decimal)(short)value, - (TypeCode.Int16, TypeCode.Double) => (double)(short)value, - (TypeCode.Int16, TypeCode.Int32) => (int)(short)value, - (TypeCode.Int16, TypeCode.Int64) => (long)(short)value, - (TypeCode.Int16, TypeCode.SByte) => (sbyte)(short)value, - (TypeCode.Int16, TypeCode.Single) => (float)(short)value, - (TypeCode.Int16, TypeCode.UInt16) => (ushort)(short)value, - (TypeCode.Int16, TypeCode.UInt32) => (uint)(short)value, - (TypeCode.Int16, TypeCode.UInt64) => (ulong)(short)value, - (TypeCode.Int32, TypeCode.Byte) => (byte)(int)value, - (TypeCode.Int32, TypeCode.Char) => (char)(int)value, - (TypeCode.Int32, TypeCode.Decimal) => (decimal)(int)value, - (TypeCode.Int32, TypeCode.Double) => (double)(int)value, - (TypeCode.Int32, TypeCode.Int16) => (short)(int)value, - (TypeCode.Int32, TypeCode.Int64) => (long)(int)value, - (TypeCode.Int32, TypeCode.SByte) => (sbyte)(int)value, - (TypeCode.Int32, TypeCode.Single) => (float)(int)value, - (TypeCode.Int32, TypeCode.UInt16) => (ushort)(int)value, - (TypeCode.Int32, TypeCode.UInt32) => (uint)(int)value, - (TypeCode.Int32, TypeCode.UInt64) => (ulong)(int)value, - (TypeCode.Int64, TypeCode.Byte) => (byte)(long)value, - (TypeCode.Int64, TypeCode.Char) => (char)(long)value, - (TypeCode.Int64, TypeCode.Decimal) => (decimal)(long)value, - (TypeCode.Int64, TypeCode.Double) => (double)(long)value, - (TypeCode.Int64, TypeCode.Int16) => (short)(long)value, - (TypeCode.Int64, TypeCode.Int32) => (int)(long)value, - (TypeCode.Int64, TypeCode.SByte) => (sbyte)(long)value, - (TypeCode.Int64, TypeCode.Single) => (float)(long)value, - (TypeCode.Int64, TypeCode.UInt16) => (ushort)(long)value, - (TypeCode.Int64, TypeCode.UInt32) => (uint)(long)value, - (TypeCode.Int64, TypeCode.UInt64) => (ulong)(long)value, - (TypeCode.SByte, TypeCode.Byte) => (byte)(sbyte)value, - (TypeCode.SByte, TypeCode.Char) => (char)(sbyte)value, - (TypeCode.SByte, TypeCode.Decimal) => (decimal)(sbyte)value, - (TypeCode.SByte, TypeCode.Double) => (double)(sbyte)value, - (TypeCode.SByte, TypeCode.Int16) => (short)(sbyte)value, - (TypeCode.SByte, TypeCode.Int32) => (int)(sbyte)value, - (TypeCode.SByte, TypeCode.Int64) => (long)(sbyte)value, - (TypeCode.SByte, TypeCode.Single) => (float)(sbyte)value, - (TypeCode.SByte, TypeCode.UInt16) => (ushort)(sbyte)value, - (TypeCode.SByte, TypeCode.UInt32) => (uint)(sbyte)value, - (TypeCode.SByte, TypeCode.UInt64) => (ulong)(sbyte)value, - (TypeCode.Single, TypeCode.Byte) => (byte)(float)value, - (TypeCode.Single, TypeCode.Char) => (char)(float)value, - (TypeCode.Single, TypeCode.Decimal) => (decimal)(float)value, - (TypeCode.Single, TypeCode.Double) => (double)(float)value, - (TypeCode.Single, TypeCode.Int16) => (short)(float)value, - (TypeCode.Single, TypeCode.Int32) => (int)(float)value, - (TypeCode.Single, TypeCode.Int64) => (long)(float)value, - (TypeCode.Single, TypeCode.SByte) => (sbyte)(float)value, - (TypeCode.Single, TypeCode.UInt16) => (ushort)(float)value, - (TypeCode.Single, TypeCode.UInt32) => (uint)(float)value, - (TypeCode.Single, TypeCode.UInt64) => (ulong)(float)value, - (TypeCode.UInt16, TypeCode.Char) => (char)(ushort)value, - (TypeCode.UInt16, TypeCode.Decimal) => (decimal)(ushort)value, - (TypeCode.UInt16, TypeCode.Double) => (double)(ushort)value, - (TypeCode.UInt16, TypeCode.Int16) => (short)(ushort)value, - (TypeCode.UInt16, TypeCode.Int32) => (int)(ushort)value, - (TypeCode.UInt16, TypeCode.Int64) => (long)(ushort)value, - (TypeCode.UInt16, TypeCode.SByte) => (sbyte)(ushort)value, - (TypeCode.UInt16, TypeCode.Single) => (float)(ushort)value, - (TypeCode.UInt16, TypeCode.UInt32) => (uint)(ushort)value, - (TypeCode.UInt16, TypeCode.UInt64) => (ulong)(ushort)value, - (TypeCode.UInt32, TypeCode.Byte) => (byte)(uint)value, - (TypeCode.UInt32, TypeCode.Char) => (char)(uint)value, - (TypeCode.UInt32, TypeCode.Decimal) => (decimal)(uint)value, - (TypeCode.UInt32, TypeCode.Double) => (double)(uint)value, - (TypeCode.UInt32, TypeCode.Int16) => (short)(uint)value, - (TypeCode.UInt32, TypeCode.Int32) => (int)(uint)value, - (TypeCode.UInt32, TypeCode.Int64) => (long)(uint)value, - (TypeCode.UInt32, TypeCode.SByte) => (sbyte)(uint)value, - (TypeCode.UInt32, TypeCode.Single) => (float)(uint)value, - (TypeCode.UInt32, TypeCode.UInt16) => (ushort)(uint)value, - (TypeCode.UInt32, TypeCode.UInt64) => (ulong)(uint)value, - (TypeCode.UInt64, TypeCode.Byte) => (byte)(ulong)value, - (TypeCode.UInt64, TypeCode.Char) => (char)(ulong)value, - (TypeCode.UInt64, TypeCode.Int16) => (short)(ulong)value, - (TypeCode.UInt64, TypeCode.Decimal) => (decimal)(ulong)value, - (TypeCode.UInt64, TypeCode.Double) => (double)(ulong)value, - (TypeCode.UInt64, TypeCode.Int32) => (int)(ulong)value, - (TypeCode.UInt64, TypeCode.Int64) => (long)(ulong)value, - (TypeCode.UInt64, TypeCode.SByte) => (sbyte)(ulong)value, - (TypeCode.UInt64, TypeCode.Single) => (float)(ulong)value, - (TypeCode.UInt64, TypeCode.UInt16) => (ushort)(ulong)value, - (TypeCode.UInt64, TypeCode.UInt32) => (uint)(ulong)value, - _ => throw new Exception($"Invalid numeric conversion: {GetTypeCodeName(fromTypeCode)} to {GetTypeCodeName(toTypeCode)}.") - }; - } - } - - private string GetTypeCodeName(TypeCode typeCode) - { - return Enum.GetName(typeof(TypeCode), typeCode); - } - } -} diff --git a/src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToAggregationExpressionTranslators/BinaryExpressionToAggregationExpressionTranslator.cs b/src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToAggregationExpressionTranslators/BinaryExpressionToAggregationExpressionTranslator.cs index bda86ed2a3d..918329fd7ac 100644 --- a/src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToAggregationExpressionTranslators/BinaryExpressionToAggregationExpressionTranslator.cs +++ b/src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToAggregationExpressionTranslators/BinaryExpressionToAggregationExpressionTranslator.cs @@ -48,6 +48,12 @@ public static AggregationExpression Translate(TranslationContext context, Binary throw new ExpressionNotSupportedException(expression, because: "operand types are not compatible with each other"); } + if (IsArithmeticExpression(expression)) + { + leftExpression = ConvertHelper.RemoveWideningConvert(leftExpression); + rightExpression = ConvertHelper.RemoveWideningConvert(rightExpression); + } + if (IsEnumExpression(expression)) { return TranslateEnumExpression(context, expression); diff --git a/src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToAggregationExpressionTranslators/ConvertExpressionToAggregationExpressionTranslator.cs b/src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToAggregationExpressionTranslators/ConvertExpressionToAggregationExpressionTranslator.cs index aeb38e26345..b7636d7740e 100644 --- a/src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToAggregationExpressionTranslators/ConvertExpressionToAggregationExpressionTranslator.cs +++ b/src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToAggregationExpressionTranslators/ConvertExpressionToAggregationExpressionTranslator.cs @@ -44,7 +44,6 @@ public static AggregationExpression Translate(TranslationContext context, UnaryE return operandTranslation; } - // must check for enum conversions before numeric conversions if (IsConvertEnumToUnderlyingType(expression)) { return TranslateConvertEnumToUnderlyingType(expression, operandTranslation); @@ -55,16 +54,6 @@ public static AggregationExpression Translate(TranslationContext context, UnaryE return TranslateConvertUnderlyingTypeToEnum(expression, operandTranslation); } - if (IsWideningNumericConversion(expression, out var sourceType, out var targetType)) - { - return TranslateWideningNumericConversion(expression, operandTranslation, sourceType, targetType); - } - - if (IsWideningNullableNumericConversion(expression, out var underlyingSourceType, out var underlyingTargetType)) - { - return TranslateWideningNullableNumericConversion(expression, operandTranslation, underlyingSourceType, underlyingTargetType); - } - if (IsConvertToBaseType(sourceType: operandExpression.Type, targetType: expressionType)) { return TranslateConvertToBaseType(expression, operandTranslation); @@ -152,22 +141,6 @@ private static bool IsConvertUnderlyingTypeToEnum(UnaryExpression expression) sourceType.IsSameAsOrNullableOf(underlyingType); } - private static bool IsWideningNumericConversion(UnaryExpression expression, out Type sourceType, out Type targetType) - { - sourceType = expression.Operand.Type; - targetType = expression.Type; - return ConvertHelper.IsWideningConvert(sourceType, targetType); - } - - private static bool IsWideningNullableNumericConversion(UnaryExpression expression, out Type underlyingSourceType, out Type underlyingTargetType) - { - var sourceType = expression.Operand.Type; - var targetType = expression.Type; - return - NumericConversionHelper.IsNullableNumericConversion(sourceType, targetType, out underlyingSourceType, out underlyingTargetType) && - ConvertHelper.IsWideningConvert(underlyingSourceType, underlyingTargetType); - } - private static AggregationExpression TranslateConvertToBaseType(UnaryExpression expression, AggregationExpression operandTranslation) { var baseType = expression.Type; @@ -263,33 +236,5 @@ private static AggregationExpression TranslateConvertUnderlyingTypeToEnum(UnaryE return new AggregationExpression(expression, operandTranslation.Ast, targetSerializer); } - - private static AggregationExpression TranslateWideningNumericConversion( - UnaryExpression expression, - AggregationExpression operandTranslation, - Type sourceType, - Type targetType) - { - var ast = operandTranslation.Ast; - var sourceSerializer = operandTranslation.Serializer; - var targetSerializer = NumericConversionHelper.CreateNumericConversionSerializer(sourceType, targetType, sourceSerializer); - - return new AggregationExpression(expression, ast, targetSerializer); - } - - private static AggregationExpression TranslateWideningNullableNumericConversion( - UnaryExpression expression, - AggregationExpression operandTranslation, - Type underlyingSourceType, - Type underlyingTargetType) - { - var ast = operandTranslation.Ast; - var sourceSerializer = (INullableSerializer)operandTranslation.Serializer; - var underlyingSourceSerializer = sourceSerializer.ValueSerializer; - var underlyingTargetSerializer = NumericConversionHelper.CreateNumericConversionSerializer(underlyingSourceType, underlyingTargetType, underlyingSourceSerializer); ; - var targetSerializer = NullableSerializer.Create(underlyingTargetSerializer); - - return new AggregationExpression(expression, ast, targetSerializer); - } } } diff --git a/src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToFilterTranslators/ToFilterFieldTranslators/ConvertExpressionToFilterFieldTranslator.cs b/src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToFilterTranslators/ToFilterFieldTranslators/ConvertExpressionToFilterFieldTranslator.cs index fbce8bc0f77..0da1aa73ecb 100644 --- a/src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToFilterTranslators/ToFilterFieldTranslators/ConvertExpressionToFilterFieldTranslator.cs +++ b/src/MongoDB.Driver/Linq/Linq3Implementation/Translators/ExpressionToFilterTranslators/ToFilterFieldTranslators/ConvertExpressionToFilterFieldTranslator.cs @@ -15,6 +15,7 @@ using System; using System.Linq.Expressions; +using MongoDB.Bson; using MongoDB.Bson.Serialization; using MongoDB.Bson.Serialization.Serializers; using MongoDB.Driver.Linq.Linq3Implementation.Ast.Filters; @@ -38,7 +39,6 @@ public static AstFilterField Translate(TranslationContext context, UnaryExpressi return field; } - // must check for enum conversions before numeric conversions if (IsConvertEnumToUnderlyingType(fieldType, targetType)) { return TranslateConvertEnumToUnderlyingType(field, targetType); @@ -54,11 +54,6 @@ public static AstFilterField Translate(TranslationContext context, UnaryExpressi return TranslateNumericConversion(field, targetType); } - if (IsNullableNumericConversion(fieldType, targetType, out var underlyingFieldType, out var underlyingTargetType)) - { - return TranslateNullableNumericConversion(field, underlyingFieldType, underlyingTargetType); - } - if (IsConvertToNullable(fieldType, targetType)) { return TranslateConvertToNullable(field); @@ -112,12 +107,29 @@ private static bool IsConvertUnderlyingTypeToEnum(Type fieldType, Type targetTyp private static bool IsNumericConversion(Type fieldType, Type targetType) { - return NumericConversionHelper.IsNumericConversion(fieldType, targetType); + return IsNumericType(fieldType) && IsNumericType(targetType); } - private static bool IsNullableNumericConversion(Type fieldType, Type targetType, out Type underlyingFieldType, out Type underlyingTargetType) + private static bool IsNumericType(Type type) { - return NumericConversionHelper.IsNullableNumericConversion(fieldType, targetType, out underlyingFieldType, out underlyingTargetType); + switch (Type.GetTypeCode(type)) + { + case TypeCode.Byte: + case TypeCode.Decimal: + case TypeCode.Double: + case TypeCode.Int16: + case TypeCode.Int32: + case TypeCode.Int64: + case TypeCode.SByte: + case TypeCode.Single: + case TypeCode.UInt16: + case TypeCode.UInt32: + case TypeCode.UInt64: + return true; + + default: + return false; + } } private static AstFilterField TranslateConvertEnumToUnderlyingType(AstFilterField field, Type targetType) @@ -199,19 +211,36 @@ private static AstFilterField TranslateConvertUnderlyingTypeToEnum(AstFilterFiel private static AstFilterField TranslateNumericConversion(AstFilterField field, Type targetType) { - var fieldSerializer = field.Serializer; - var fieldType = fieldSerializer.ValueType; - var targetSerializer = NumericConversionHelper.CreateNumericConversionSerializer(fieldType, targetType, fieldSerializer); - return AstFilter.Field(field.Path, targetSerializer); - } - - private static AstFilterField TranslateNullableNumericConversion(AstFilterField field, Type underlyingFieldType, Type underlyingTargetType) - { - var fieldSerializer = (INullableSerializer)field.Serializer; - var underlyingFieldSerializer = fieldSerializer.ValueSerializer; - var underlyingTargetSerializer = NumericConversionHelper.CreateNumericConversionSerializer(underlyingFieldType, underlyingTargetType, underlyingFieldSerializer); - var targetSerializer = NullableSerializer.Create(underlyingTargetSerializer); - return AstFilter.Field(field.Path, targetSerializer); + IBsonSerializer targetTypeSerializer = targetType switch + { + Type t when t == typeof(byte) => new ByteSerializer(), + Type t when t == typeof(sbyte) => new SByteSerializer(), + Type t when t == typeof(short) => new Int16Serializer(), + Type t when t == typeof(ushort) => new UInt16Serializer(), + Type t when t == typeof(int) => new Int32Serializer(), + Type t when t == typeof(uint) => new UInt32Serializer(), + Type t when t == typeof(long) => new Int64Serializer(), + Type t when t == typeof(ulong) => new UInt64Serializer(), + Type t when t == typeof(float) => new SingleSerializer(), + Type t when t == typeof(double) => new DoubleSerializer(), + Type t when t == typeof(decimal) => new DecimalSerializer(), + _ => throw new Exception($"Unexpected target type: {targetType}.") + }; + if (field.Serializer is IRepresentationConfigurable representationConfigurableFieldSerializer && + targetTypeSerializer is IRepresentationConfigurable representationConfigurableTargetTypeSerializer) + { + var fieldRepresentation = representationConfigurableFieldSerializer.Representation; + if (fieldRepresentation == BsonType.String) + { + targetTypeSerializer = representationConfigurableTargetTypeSerializer.WithRepresentation(fieldRepresentation); + } + } + if (field.Serializer is IRepresentationConverterConfigurable converterConfigurableFieldSerializer && + targetTypeSerializer is IRepresentationConverterConfigurable converterConfigurableTargetTypeSerializer) + { + targetTypeSerializer = converterConfigurableTargetTypeSerializer.WithConverter(converterConfigurableFieldSerializer.Converter); + } + return AstFilter.Field(field.Path, targetTypeSerializer); } } } diff --git a/src/MongoDB.Driver/Linq/Linq3Implementation/Translators/NumericConversionHelper.cs b/src/MongoDB.Driver/Linq/Linq3Implementation/Translators/NumericConversionHelper.cs deleted file mode 100644 index 6ed0e2683f0..00000000000 --- a/src/MongoDB.Driver/Linq/Linq3Implementation/Translators/NumericConversionHelper.cs +++ /dev/null @@ -1,123 +0,0 @@ -/* Copyright 2010-present MongoDB Inc. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -using System; -using MongoDB.Bson; -using MongoDB.Bson.Serialization; -using MongoDB.Bson.Serialization.Options; -using MongoDB.Bson.Serialization.Serializers; -using MongoDB.Driver.Linq.Linq3Implementation.Misc; -using MongoDB.Driver.Linq.Linq3Implementation.Serializers; -using MongoDB.Driver.Support; - -namespace MongoDB.Driver.Linq.Linq3Implementation.Translators -{ - /// - /// Helper methods related to numeric conversions. - /// - internal static class NumericConversionHelper - { - public static IBsonSerializer CreateNumericConversionSerializer( - Type sourceType, - Type targetType, - IBsonSerializer sourceSerializer) - { - if (ConvertHelper.IsWideningConvert(sourceType, targetType) && - sourceSerializer is IBsonNumericSerializer sourceNumericSerializer && - sourceNumericSerializer.Representation.IsNumericRepresentation()) - { - return CreateWiderNumericSerializer(targetType, sourceNumericSerializer.Converter); - } - else - { - return ConvertingNumericSerializer.Create(sourceType, targetType, sourceSerializer); - } - } - - public static IBsonSerializer CreateWiderNumericSerializer(Type widerType, RepresentationConverter converter) - { - return - Type.GetTypeCode(widerType) switch - { - TypeCode.Char => new CharSerializer(BsonType.Int32, converter), - TypeCode.Decimal => new DecimalSerializer(BsonType.Decimal128, converter), - TypeCode.Double => new DoubleSerializer(BsonType.Double, converter), - TypeCode.Int16 => new Int16Serializer(BsonType.Int32, converter), - TypeCode.Int32 => new Int32Serializer(BsonType.Int32, converter), - TypeCode.Int64 => new Int64Serializer(BsonType.Int64, converter), - TypeCode.SByte => new SByteSerializer(BsonType.Int32, converter), - TypeCode.Single => new SingleSerializer(BsonType.Double, converter), - TypeCode.UInt16 => new UInt16Serializer(BsonType.Int32, converter), - TypeCode.UInt32 => new UInt32Serializer(BsonType.Int32, converter), - TypeCode.UInt64 => new UInt64Serializer(BsonType.Int64, converter), - _ => throw new ArgumentException($"Unexpected type code: {Type.GetTypeCode(widerType)}"), - }; - } - - public static bool IsNumericConversion(Type sourceType, Type targetType) - { - return IsNumericType(sourceType) && IsNumericType(targetType); - } - - public static bool IsNullableNumericConversion(Type sourceType, Type targetType, out Type underlyingSourceType, out Type underlyingTargetType) - { - if (sourceType.IsNullable(out underlyingSourceType) && - targetType.IsNullable(out underlyingTargetType) && - IsNumericConversion(underlyingSourceType, underlyingTargetType)) - { - return true; - } - - underlyingSourceType = null; - underlyingTargetType = null; - return false; - } - - private static bool IsNumericRepresentation(this BsonType bsonType) - { - return bsonType switch - { - BsonType.Decimal128 or - BsonType.Double or - BsonType.Int32 or - BsonType.Int64 => true, - _ => false - }; - } - - private static bool IsNumericType(Type type) - { - switch (Type.GetTypeCode(type)) - { - case TypeCode.Byte: - case TypeCode.Char: - case TypeCode.Decimal: - case TypeCode.Double: - case TypeCode.Int16: - case TypeCode.Int32: - case TypeCode.Int64: - case TypeCode.SByte: - case TypeCode.Single: - case TypeCode.UInt16: - case TypeCode.UInt32: - case TypeCode.UInt64: - return true; - - default: - return false; - } - } - } -} diff --git a/tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/Jira/CSharp4566Tests.cs b/tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/Jira/CSharp4566Tests.cs deleted file mode 100644 index 6e1d7510fea..00000000000 --- a/tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/Jira/CSharp4566Tests.cs +++ /dev/null @@ -1,1521 +0,0 @@ -/* Copyright 2010-present MongoDB Inc. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -using System.Linq; -using FluentAssertions; -using MongoDB.Bson; -using MongoDB.Bson.Serialization.Attributes; -using MongoDB.Driver.Linq; -using MongoDB.Driver.Tests.Linq.Linq3Implementation; -using MongoDB.TestHelpers.XunitExtensions; -using Xunit; - -namespace MongoDB.Driver.Tests.Linq.Linq3ImplementationTests.Jira -{ - public class CSharp4566Tests : Linq3IntegrationTest - { - [Theory] - [ParameterAttributeData] - public void Filter_with_byte_should_work( - [Values(LinqProvider.V2, LinqProvider.V3)] LinqProvider linqProvider) - { - var collection = CreateCollection(linqProvider); - - var find = collection - .Find(x => x.Byte == 1); - - var filter = TranslateFindFilter(collection, find); - filter.Should().Be("{ Byte : 1 }"); - - var results = find.ToList(); - results.Select(x => x.Id).Should().Equal(1); - } - - [Theory] - [ParameterAttributeData] - public void Filter_with_char_should_work( - [Values(LinqProvider.V2, LinqProvider.V3)] LinqProvider linqProvider) - { - var collection = CreateCollection(linqProvider); - - var find = collection - .Find(x => x.Char == 'a'); - - var filter = TranslateFindFilter(collection, find); - filter.Should().Be("{ Char : 97 }"); - - var results = find.ToList(); - results.Select(x => x.Id).Should().Equal(1); - } - - [Theory] - [ParameterAttributeData] - public void Filter_with_char_with_string_representation_should_work( - [Values(LinqProvider.V2, LinqProvider.V3)] LinqProvider linqProvider) - { - var collection = CreateCollection(linqProvider); - - var find = collection - .Find(x => x.CharWithStringRepresentation == 'a'); - - var filter = TranslateFindFilter(collection, find); - filter.Should().Be("{ CharWithStringRepresentation : 'a' }"); - - var results = find.ToList(); - results.Select(x => x.Id).Should().Equal(1); - } - - [Theory] - [ParameterAttributeData] - public void Filter_with_decimal_should_work( - [Values(LinqProvider.V2, LinqProvider.V3)] LinqProvider linqProvider) - { - var collection = CreateCollection(linqProvider); - - var find = collection - .Find(x => x.Decimal == 1); - - var filter = TranslateFindFilter(collection, find); - filter.Should().Be("{ Decimal : '1' }"); - - var results = find.ToList(); - results.Select(x => x.Id).Should().Equal(1); - } - - [Theory] - [ParameterAttributeData] - public void Filter_with_decimal_with_numeric_representation_should_work( - [Values(LinqProvider.V2, LinqProvider.V3)] LinqProvider linqProvider) - { - var collection = CreateCollection(linqProvider); - - var find = collection - .Find(x => x.DecimalWithNumericRepresentation == 1); - - var filter = TranslateFindFilter(collection, find); - filter.Should().Be("{ DecimalWithNumericRepresentation : { $numberDecimal : '1' } }"); - - var results = find.ToList(); - results.Select(x => x.Id).Should().Equal(1); - } - - [Theory] - [ParameterAttributeData] - public void Filter_with_Decimal128_should_work( - [Values(LinqProvider.V2, LinqProvider.V3)] LinqProvider linqProvider) - { - var collection = CreateCollection(linqProvider); - - var find = collection - .Find(x => x.Decimal128 == 1); - - var filter = TranslateFindFilter(collection, find); - filter.Should().Be("{ Decimal128 : '1' }"); - - var results = find.ToList(); - results.Select(x => x.Id).Should().Equal(1); - } - - [Theory] - [ParameterAttributeData] - public void Filter_with_Decimal128_with_numeric_representation_should_work( - [Values(LinqProvider.V2, LinqProvider.V3)] LinqProvider linqProvider) - { - var collection = CreateCollection(linqProvider); - - var find = collection - .Find(x => x.Decimal128WithNumericRepresentation == 1); - - var filter = TranslateFindFilter(collection, find); - filter.Should().Be("{ Decimal128WithNumericRepresentation : { $numberDecimal : '1' } }"); - - var results = find.ToList(); - results.Select(x => x.Id).Should().Equal(1); - } - - [Theory] - [ParameterAttributeData] - public void Filter_with_Double_should_work( - [Values(LinqProvider.V2, LinqProvider.V3)] LinqProvider linqProvider) - { - var collection = CreateCollection(linqProvider); - - var find = collection - .Find(x => x.Double == 1); - - var filter = TranslateFindFilter(collection, find); - filter.Should().Be("{ Double : 1.0 }"); - - var results = find.ToList(); - results.Select(x => x.Id).Should().Equal(1); - } - - [Theory] - [ParameterAttributeData] - public void Filter_with_Int16_should_work( - [Values(LinqProvider.V2, LinqProvider.V3)] LinqProvider linqProvider) - { - var collection = CreateCollection(linqProvider); - - var find = collection - .Find(x => x.Int16 == 1); - - var filter = TranslateFindFilter(collection, find); - filter.Should().Be("{ Int16 : 1 }"); - - var results = find.ToList(); - results.Select(x => x.Id).Should().Equal(1); - } - - [Theory] - [ParameterAttributeData] - public void Filter_with_Int32_should_work( - [Values(LinqProvider.V2, LinqProvider.V3)] LinqProvider linqProvider) - { - var collection = CreateCollection(linqProvider); - - var find = collection - .Find(x => x.Int32 == 1); - - var filter = TranslateFindFilter(collection, find); - filter.Should().Be("{ Int32 : 1 }"); - - var results = find.ToList(); - results.Select(x => x.Id).Should().Equal(1); - } - - [Theory] - [ParameterAttributeData] - public void Filter_with_Int64_should_work( - [Values(LinqProvider.V2, LinqProvider.V3)] LinqProvider linqProvider) - { - var collection = CreateCollection(linqProvider); - - var find = collection - .Find(x => x.Int64 == 1); - - var filter = TranslateFindFilter(collection, find); - filter.Should().Be("{ Int64 : { $numberLong : 1 } }"); - - var results = find.ToList(); - results.Select(x => x.Id).Should().Equal(1); - } - - [Theory] - [ParameterAttributeData] - public void Filter_with_SByte_should_work( - [Values(LinqProvider.V2, LinqProvider.V3)] LinqProvider linqProvider) - { - var collection = CreateCollection(linqProvider); - - var find = collection - .Find(x => x.SByte == 1); - - var filter = TranslateFindFilter(collection, find); - filter.Should().Be("{ SByte : 1 }"); - - var results = find.ToList(); - results.Select(x => x.Id).Should().Equal(1); - } - - [Theory] - [ParameterAttributeData] - public void Filter_with_Single_should_work( - [Values(LinqProvider.V2, LinqProvider.V3)] LinqProvider linqProvider) - { - var collection = CreateCollection(linqProvider); - - var find = collection - .Find(x => x.Single == 1); - - var filter = TranslateFindFilter(collection, find); - filter.Should().Be("{ Single : 1.0 }"); - - var results = find.ToList(); - results.Select(x => x.Id).Should().Equal(1); - } - - [Theory] - [ParameterAttributeData] - public void Filter_with_Single_compared_to_Double_constant_should_work( - [Values(LinqProvider.V2, LinqProvider.V3)] LinqProvider linqProvider) - { - var collection = CreateCollection(linqProvider); - - var find = collection - .Find(x => x.Single == 1.0); - - var filter = TranslateFindFilter(collection, find); - filter.Should().Be("{ Single : 1.0 }"); - - var results = find.ToList(); - results.Select(x => x.Id).Should().Equal(1); - } - - [Theory] - [ParameterAttributeData] - public void Filter_with_UInt16_should_work( - [Values(LinqProvider.V2, LinqProvider.V3)] LinqProvider linqProvider) - { - var collection = CreateCollection(linqProvider); - - var find = collection - .Find(x => x.UInt16 == 1); - - var filter = TranslateFindFilter(collection, find); - filter.Should().Be("{ UInt16 : 1 }"); - - var results = find.ToList(); - results.Select(x => x.Id).Should().Equal(1); - } - - [Theory] - [ParameterAttributeData] - public void Filter_with_UInt32_should_work( - [Values(LinqProvider.V2, LinqProvider.V3)] LinqProvider linqProvider) - { - var collection = CreateCollection(linqProvider); - - var find = collection - .Find(x => x.UInt32 == 1); - - var filter = TranslateFindFilter(collection, find); - filter.Should().Be("{ UInt32 : 1 }"); - - var results = find.ToList(); - results.Select(x => x.Id).Should().Equal(1); - } - - [Theory] - [ParameterAttributeData] - public void Filter_with_UInt64_should_work( - [Values(LinqProvider.V2, LinqProvider.V3)] LinqProvider linqProvider) - { - var collection = CreateCollection(linqProvider); - - var find = collection - .Find(x => x.UInt64 == 1); - - var filter = TranslateFindFilter(collection, find); - filter.Should().Be("{ UInt64 : { $numberLong : 1 } }"); - - var results = find.ToList(); - results.Select(x => x.Id).Should().Equal(1); - } - - [Theory] - [InlineData((byte)1, "{ NullableByte : 1 }", 1, LinqProvider.V2)] - [InlineData((byte)1, "{ NullableByte : 1 }", 1, LinqProvider.V3)] - [InlineData(null, "{ NullableByte : null }", 3, LinqProvider.V2)] - [InlineData(null, "{ NullableByte : null }", 3, LinqProvider.V3)] - public void Filter_with_nullable_byte_should_work(byte? value, string expectedFilter, int expectedId, LinqProvider linqProvider) - { - var collection = CreateCollection(linqProvider); - - var find = collection - .Find(x => x.NullableByte == value); - - var filter = TranslateFindFilter(collection, find); - filter.Should().Be(expectedFilter); - - var results = find.ToList(); - results.Select(x => x.Id).Should().Equal(expectedId); - } - - [Theory] - [InlineData('a', "{ NullableChar : 97 }", 1, LinqProvider.V2)] - [InlineData('a', "{ NullableChar : 97 }", 1, LinqProvider.V3)] - [InlineData(null, "{ NullableChar : null }", 3, LinqProvider.V2)] - [InlineData(null, "{ NullableChar : null }", 3, LinqProvider.V3)] - public void Filter_with_nullable_char_should_work(char? value, string expectedFilter, int expectedId, LinqProvider linqProvider) - { - var collection = CreateCollection(linqProvider); - - var find = collection - .Find(x => x.NullableChar == value); - - var filter = TranslateFindFilter(collection, find); - filter.Should().Be(expectedFilter); - - var results = find.ToList(); - results.Select(x => x.Id).Should().Equal(expectedId); - } - - [Theory] - [InlineData('a', "{ NullableCharWithStringRepresentation : 97 }", new int[0], LinqProvider.V2)] // note: LINQ2 translated is wrong - [InlineData('a', "{ NullableCharWithStringRepresentation : 'a' }", new[] { 1 }, LinqProvider.V3)] - [InlineData(null, "{ NullableCharWithStringRepresentation : null }", new[] { 3 }, LinqProvider.V2)] - [InlineData(null, "{ NullableCharWithStringRepresentation : null }", new[] { 3 }, LinqProvider.V3)] - public void Filter_with_nullable_char_with_string_representation_should_work(char? value, string expectedFilter, int[] expectedIds, LinqProvider linqProvider) - { - var collection = CreateCollection(linqProvider); - - var find = collection - .Find(x => x.NullableCharWithStringRepresentation == value); - - var filter = TranslateFindFilter(collection, find); - filter.Should().Be(expectedFilter); - - var results = find.ToList(); - results.Select(x => x.Id).Should().Equal(expectedIds); - } - - [Theory] - [ParameterAttributeData] - public void Filter_with_nullable_decimal_should_work( - [Values(LinqProvider.V2, LinqProvider.V3)] LinqProvider linqProvider) - { - var collection = CreateCollection(linqProvider); - - var find = collection - .Find(x => x.NullableDecimal == 1); - - var filter = TranslateFindFilter(collection, find); - filter.Should().Be("{ NullableDecimal : '1' }"); - - var results = find.ToList(); - results.Select(x => x.Id).Should().Equal(1); - } - - [Theory] - [ParameterAttributeData] - public void Filter_with_nullable_decimal_with_numeric_representation_should_work( - [Values(LinqProvider.V2, LinqProvider.V3)] LinqProvider linqProvider) - { - var collection = CreateCollection(linqProvider); - - var find = collection - .Find(x => x.NullableDecimalWithNumericRepresentation == 1); - - var filter = TranslateFindFilter(collection, find); - filter.Should().Be("{ NullableDecimalWithNumericRepresentation : { $numberDecimal : '1' } }"); - - var results = find.ToList(); - results.Select(x => x.Id).Should().Equal(1); - } - - [Theory] - [ParameterAttributeData] - public void Filter_with_nullable_Decimal128_should_work( - [Values(LinqProvider.V2, LinqProvider.V3)] LinqProvider linqProvider) - { - var collection = CreateCollection(linqProvider); - - var find = collection - .Find(x => x.NullableDecimal128 == 1); - - var filter = TranslateFindFilter(collection, find); - filter.Should().Be("{ NullableDecimal128 : '1' }"); - - var results = find.ToList(); - results.Select(x => x.Id).Should().Equal(1); - } - - [Theory] - [ParameterAttributeData] - public void Filter_with_nullable_Decimal128_with_numeric_representation_should_work( - [Values(LinqProvider.V2, LinqProvider.V3)] LinqProvider linqProvider) - { - var collection = CreateCollection(linqProvider); - - var find = collection - .Find(x => x.NullableDecimal128WithNumericRepresentation == 1); - - var filter = TranslateFindFilter(collection, find); - filter.Should().Be("{ NullableDecimal128WithNumericRepresentation : { $numberDecimal : '1' } }"); - - var results = find.ToList(); - results.Select(x => x.Id).Should().Equal(1); - } - - [Theory] - [ParameterAttributeData] - public void Filter_with_nullable_Double_should_work( - [Values(LinqProvider.V2, LinqProvider.V3)] LinqProvider linqProvider) - { - var collection = CreateCollection(linqProvider); - - var find = collection - .Find(x => x.NullableDouble == 1); - - var filter = TranslateFindFilter(collection, find); - filter.Should().Be("{ NullableDouble : 1.0 }"); - - var results = find.ToList(); - results.Select(x => x.Id).Should().Equal(1); - } - - [Theory] - [ParameterAttributeData] - public void Filter_with_nullable_Int16_should_work( - [Values(LinqProvider.V2, LinqProvider.V3)] LinqProvider linqProvider) - { - var collection = CreateCollection(linqProvider); - - var find = collection - .Find(x => x.NullableInt16 == 1); - - var filter = TranslateFindFilter(collection, find); - filter.Should().Be("{ NullableInt16 : 1 }"); - - var results = find.ToList(); - results.Select(x => x.Id).Should().Equal(1); - } - - [Theory] - [ParameterAttributeData] - public void Filter_with_nullable_Int32_should_work( - [Values(LinqProvider.V2, LinqProvider.V3)] LinqProvider linqProvider) - { - var collection = CreateCollection(linqProvider); - - var find = collection - .Find(x => x.NullableInt32 == 1); - - var filter = TranslateFindFilter(collection, find); - filter.Should().Be("{ NullableInt32 : 1 }"); - - var results = find.ToList(); - results.Select(x => x.Id).Should().Equal(1); - } - - [Theory] - [ParameterAttributeData] - public void Filter_with_nullable_Int64_should_work( - [Values(LinqProvider.V2, LinqProvider.V3)] LinqProvider linqProvider) - { - var collection = CreateCollection(linqProvider); - - var find = collection - .Find(x => x.NullableInt64 == 1); - - var filter = TranslateFindFilter(collection, find); - filter.Should().Be("{ NullableInt64 : { $numberLong : 1 } }"); - - var results = find.ToList(); - results.Select(x => x.Id).Should().Equal(1); - } - - [Theory] - [ParameterAttributeData] - public void Filter_with_nullable_SByte_should_work( - [Values(LinqProvider.V2, LinqProvider.V3)] LinqProvider linqProvider) - { - var collection = CreateCollection(linqProvider); - - var find = collection - .Find(x => x.NullableSByte == 1); - - var filter = TranslateFindFilter(collection, find); - filter.Should().Be("{ NullableSByte : 1 }"); - - var results = find.ToList(); - results.Select(x => x.Id).Should().Equal(1); - } - - [Theory] - [ParameterAttributeData] - public void Filter_with_nullable_Single_should_work( - [Values(LinqProvider.V2, LinqProvider.V3)] LinqProvider linqProvider) - { - var collection = CreateCollection(linqProvider); - - var find = collection - .Find(x => x.NullableSingle == 1); - - var filter = TranslateFindFilter(collection, find); - filter.Should().Be("{ NullableSingle : 1.0 }"); - - var results = find.ToList(); - results.Select(x => x.Id).Should().Equal(1); - } - - [Theory] - [ParameterAttributeData] - public void Filter_with_nullable_Single_compared_to_Double_constant_should_work( - [Values(LinqProvider.V2, LinqProvider.V3)] LinqProvider linqProvider) - { - var collection = CreateCollection(linqProvider); - - var find = collection - .Find(x => x.NullableSingle == 1.0); - - var filter = TranslateFindFilter(collection, find); - filter.Should().Be("{ NullableSingle : 1.0 }"); - - var results = find.ToList(); - results.Select(x => x.Id).Should().Equal(1); - } - - [Theory] - [ParameterAttributeData] - public void Filter_with_nullable_UInt16_should_work( - [Values(LinqProvider.V2, LinqProvider.V3)] LinqProvider linqProvider) - { - var collection = CreateCollection(linqProvider); - - var find = collection - .Find(x => x.NullableUInt16 == 1); - - var filter = TranslateFindFilter(collection, find); - filter.Should().Be("{ NullableUInt16 : 1 }"); - - var results = find.ToList(); - results.Select(x => x.Id).Should().Equal(1); - } - - [Theory] - [ParameterAttributeData] - public void Filter_with_nullable_UInt32_should_work( - [Values(LinqProvider.V2, LinqProvider.V3)] LinqProvider linqProvider) - { - var collection = CreateCollection(linqProvider); - - var find = collection - .Find(x => x.NullableUInt32 == 1); - - var filter = TranslateFindFilter(collection, find); - filter.Should().Be("{ NullableUInt32 : 1 }"); - - var results = find.ToList(); - results.Select(x => x.Id).Should().Equal(1); - } - - [Theory] - [ParameterAttributeData] - public void Filter_with_nullable_UInt64_should_work( - [Values(LinqProvider.V2, LinqProvider.V3)] LinqProvider linqProvider) - { - var collection = CreateCollection(linqProvider); - - var find = collection - .Find(x => x.NullableUInt64 == 1); - - var filter = TranslateFindFilter(collection, find); - filter.Should().Be("{ NullableUInt64 : { $numberLong : 1 } }"); - - var results = find.ToList(); - results.Select(x => x.Id).Should().Equal(1); - } - - [Theory] - [ParameterAttributeData] - public void Select_with_byte_should_work( - [Values(LinqProvider.V2, LinqProvider.V3)] LinqProvider linqProvider) - { - var collection = CreateCollection(linqProvider); - - var queryable = collection.AsQueryable() - .Select(x => x.Byte == 1); - - var stages = Translate(collection, queryable); - if (linqProvider == LinqProvider.V2) - { - AssertStages(stages, "{ $project : { __fld0 : { $eq : ['$Byte', 1] }, _id : 0 } }"); - } - else - { - AssertStages(stages, "{ $project : { _v : { $eq : ['$Byte', 1] }, _id : 0 } }"); - } - - var results = queryable.ToList(); - results.Should().Equal(true, false, false); - } - - [Theory] - [ParameterAttributeData] - public void Select_with_char_should_work( - [Values(LinqProvider.V2, LinqProvider.V3)] LinqProvider linqProvider) - { - var collection = CreateCollection(linqProvider); - - var queryable = collection.AsQueryable() - .Select(x => x.Char == 'a'); - - var stages = Translate(collection, queryable); - if (linqProvider == LinqProvider.V2) - { - AssertStages(stages, "{ $project : { __fld0 : { $eq : ['$Char', 97] }, _id : 0 } }"); - } - else - { - AssertStages(stages, "{ $project : { _v : { $eq : ['$Char', 97] }, _id : 0 } }"); - } - - var results = queryable.ToList(); - results.Should().Equal(true, false, false); - } - - [Theory] - [ParameterAttributeData] - public void Select_with_char_with_string_representation_should_work( - [Values(LinqProvider.V2, LinqProvider.V3)] LinqProvider linqProvider) - { - var collection = CreateCollection(linqProvider); - - var queryable = collection.AsQueryable() - .Select(x => x.CharWithStringRepresentation == 'a'); - - var stages = Translate(collection, queryable); - var results = queryable.ToList(); - if (linqProvider == LinqProvider.V2) - { - AssertStages(stages, "{ $project : { __fld0 : { $eq : ['$CharWithStringRepresentation', 97] }, _id : 0 } }"); // note: LINQ2 translation is wrong - results.Should().Equal(false, false, false); // note: LINQ2 results are wrong - } - else - { - AssertStages(stages, "{ $project : { _v : { $eq : ['$CharWithStringRepresentation', 'a'] }, _id : 0 } }"); - results.Should().Equal(true, false, false); - } - } - - [Theory] - [ParameterAttributeData] - public void Select_with_decimal_should_work( - [Values(LinqProvider.V2, LinqProvider.V3)] LinqProvider linqProvider) - { - var collection = CreateCollection(linqProvider); - - var queryable = collection.AsQueryable() - .Select(x => x.Decimal == 1); - - var stages = Translate(collection, queryable); - var results = queryable.ToList(); - if (linqProvider == LinqProvider.V2) - { - AssertStages(stages, "{ $project : { __fld0 : { $eq : ['$Decimal', { $numberDecimal : '1' }] }, _id : 0 } }"); // note: LINQ2 translation is wrong - results.Should().Equal(false, false, false); // note: LINQ2 results are wrong - } - else - { - AssertStages(stages, "{ $project : { _v : { $eq : ['$Decimal', '1'] }, _id : 0 } }"); - results.Should().Equal(true, false, false); - } - } - - [Theory] - [ParameterAttributeData] - public void Select_with_decimal_with_numeric_representation_should_work( - [Values(LinqProvider.V2, LinqProvider.V3)] LinqProvider linqProvider) - { - var collection = CreateCollection(linqProvider); - - var queryable = collection.AsQueryable() - .Select(x => x.DecimalWithNumericRepresentation == 1); - - var stages = Translate(collection, queryable); - if (linqProvider == LinqProvider.V2) - { - AssertStages(stages, "{ $project : { __fld0 : { $eq : ['$DecimalWithNumericRepresentation', { $numberDecimal : '1' }] }, _id : 0 } }"); - } - else - { - AssertStages(stages, "{ $project : { _v : { $eq : ['$DecimalWithNumericRepresentation', { $numberDecimal : '1' }] }, _id : 0 } }"); - } - - var results = queryable.ToList(); - results.Should().Equal(true, false, false); - } - - [Theory] - [ParameterAttributeData] - public void Select_with_Decimal128_should_work( - [Values(LinqProvider.V2, LinqProvider.V3)] LinqProvider linqProvider) - { - var collection = CreateCollection(linqProvider); - - var queryable = collection.AsQueryable() - .Select(x => x.Decimal128 == 1); - - var stages = Translate(collection, queryable); - var results = queryable.ToList(); - if (linqProvider == LinqProvider.V2) - { - AssertStages(stages, "{ $project : { __fld0 : { $eq : ['$Decimal128', { $numberDecimal : '1' }] }, _id : 0 } }"); // note: LINQ2 translation is wrong - results.Should().Equal(false, false, false); // note: LINQ2 results are wrong - } - else - { - AssertStages(stages, "{ $project : { _v : { $eq : ['$Decimal128', '1'] }, _id : 0 } }"); - results.Should().Equal(true, false, false); - } - } - - [Theory] - [ParameterAttributeData] - public void Select_with_Decimal128_with_numeric_representation_should_work( - [Values(LinqProvider.V2, LinqProvider.V3)] LinqProvider linqProvider) - { - var collection = CreateCollection(linqProvider); - - var queryable = collection.AsQueryable() - .Select(x => x.Decimal128WithNumericRepresentation == 1); - - var stages = Translate(collection, queryable); - if (linqProvider == LinqProvider.V2) - { - AssertStages(stages, "{ $project : { __fld0 : { $eq : ['$Decimal128WithNumericRepresentation', { $numberDecimal : '1' }] }, _id : 0 } }"); - } - else - { - AssertStages(stages, "{ $project : { _v : { $eq : ['$Decimal128WithNumericRepresentation', { $numberDecimal : '1' }] }, _id : 0 } }"); - } - - var results = queryable.ToList(); - results.Should().Equal(true, false, false); - } - - [Theory] - [ParameterAttributeData] - public void Select_with_Double_should_work( - [Values(LinqProvider.V2, LinqProvider.V3)] LinqProvider linqProvider) - { - var collection = CreateCollection(linqProvider); - - var queryable = collection.AsQueryable() - .Select(x => x.Double == 1); - - var stages = Translate(collection, queryable); - if (linqProvider == LinqProvider.V2) - { - AssertStages(stages, "{ $project : { __fld0 : { $eq : ['$Double', 1.0] }, _id : 0 } }"); - } - else - { - AssertStages(stages, "{ $project : { _v : { $eq : ['$Double', 1.0] }, _id : 0 } }"); - } - - var results = queryable.ToList(); - results.Should().Equal(true, false, false); - } - - [Theory] - [ParameterAttributeData] - public void Select_with_Int16_should_work( - [Values(LinqProvider.V2, LinqProvider.V3)] LinqProvider linqProvider) - { - var collection = CreateCollection(linqProvider); - - var queryable = collection.AsQueryable() - .Select(x => x.Int16 == 1); - - var stages = Translate(collection, queryable); - if (linqProvider == LinqProvider.V2) - { - AssertStages(stages, "{ $project : { __fld0 : { $eq : ['$Int16', 1] }, _id : 0 } }"); - } - else - { - AssertStages(stages, "{ $project : { _v : { $eq : ['$Int16', 1] }, _id : 0 } }"); - } - - var results = queryable.ToList(); - results.Should().Equal(true, false, false); - } - - [Theory] - [ParameterAttributeData] - public void Select_with_Int32_should_work( - [Values(LinqProvider.V2, LinqProvider.V3)] LinqProvider linqProvider) - { - var collection = CreateCollection(linqProvider); - - var queryable = collection.AsQueryable() - .Select(x => x.Int32 == 1); - - var stages = Translate(collection, queryable); - if (linqProvider == LinqProvider.V2) - { - AssertStages(stages, "{ $project : { __fld0 : { $eq : ['$Int32', 1] }, _id : 0 } }"); - } - else - { - AssertStages(stages, "{ $project : { _v : { $eq : ['$Int32', 1] }, _id : 0 } }"); - } - - var results = queryable.ToList(); - results.Should().Equal(true, false, false); - } - - [Theory] - [ParameterAttributeData] - public void Select_with_Int64_should_work( - [Values(LinqProvider.V2, LinqProvider.V3)] LinqProvider linqProvider) - { - var collection = CreateCollection(linqProvider); - - var queryable = collection.AsQueryable() - .Select(x => x.Int64 == 1); - - var stages = Translate(collection, queryable); - if (linqProvider == LinqProvider.V2) - { - AssertStages(stages, "{ $project : { __fld0 : { $eq : ['$Int64', { $numberLong : 1 }] }, _id : 0 } }"); - } - else - { - AssertStages(stages, "{ $project : { _v : { $eq : ['$Int64', { $numberLong : 1 }] }, _id : 0 } }"); - } - - var results = queryable.ToList(); - results.Should().Equal(true, false, false); - } - - [Theory] - [ParameterAttributeData] - public void Select_with_SByte_should_work( - [Values(LinqProvider.V2, LinqProvider.V3)] LinqProvider linqProvider) - { - var collection = CreateCollection(linqProvider); - - var queryable = collection.AsQueryable() - .Select(x => x.SByte == 1); - - var stages = Translate(collection, queryable); - if (linqProvider == LinqProvider.V2) - { - AssertStages(stages, "{ $project : { __fld0 : { $eq : ['$SByte', 1] }, _id : 0 } }"); - } - else - { - AssertStages(stages, "{ $project : { _v : { $eq : ['$SByte', 1] }, _id : 0 } }"); - } - - var results = queryable.ToList(); - results.Should().Equal(true, false, false); - } - - [Theory] - [ParameterAttributeData] - public void Select_with_Single_should_work( - [Values(LinqProvider.V2, LinqProvider.V3)] LinqProvider linqProvider) - { - var collection = CreateCollection(linqProvider); - - var queryable = collection.AsQueryable() - .Select(x => x.Single == 1); - - var stages = Translate(collection, queryable); - if (linqProvider == LinqProvider.V2) - { - AssertStages(stages, "{ $project : { __fld0 : { $eq : ['$Single', 1.0] }, _id : 0 } }"); - } - else - { - AssertStages(stages, "{ $project : { _v : { $eq : ['$Single', 1.0] }, _id : 0 } }"); - } - - var results = queryable.ToList(); - results.Should().Equal(true, false, false); - } - - [Theory] - [ParameterAttributeData] - public void Select_with_Single_compared_to_Double_constant_should_work( - [Values(LinqProvider.V2, LinqProvider.V3)] LinqProvider linqProvider) - { - var collection = CreateCollection(linqProvider); - - var queryable = collection.AsQueryable() - .Select(x => x.Single == 1.0); - - var stages = Translate(collection, queryable); - if (linqProvider == LinqProvider.V2) - { - AssertStages(stages, "{ $project : { __fld0 : { $eq : ['$Single', 1.0] }, _id : 0 } }"); - } - else - { - AssertStages(stages, "{ $project : { _v : { $eq : ['$Single', 1.0] }, _id : 0 } }"); - } - - var results = queryable.ToList(); - results.Should().Equal(true, false, false); - } - - [Theory] - [ParameterAttributeData] - public void Select_with_Single_compared_to_Double_field_should_work( - [Values(LinqProvider.V2, LinqProvider.V3)] LinqProvider linqProvider) - { - var collection = CreateCollection(linqProvider); - - var queryable = collection.AsQueryable() - .Select(x => x.Single == x.Double); - - var stages = Translate(collection, queryable); - if (linqProvider == LinqProvider.V2) - { - AssertStages(stages, "{ $project : { __fld0 : { $eq : ['$Single', '$Double'] }, _id : 0 } }"); - } - else - { - AssertStages(stages, "{ $project : { _v : { $eq : ['$Single', '$Double'] }, _id : 0 } }"); - } - - var results = queryable.ToList(); - results.Should().Equal(true, true, true); - } - - [Theory] - [ParameterAttributeData] - public void Select_with_UInt16_should_work( - [Values(LinqProvider.V2, LinqProvider.V3)] LinqProvider linqProvider) - { - var collection = CreateCollection(linqProvider); - - var queryable = collection.AsQueryable() - .Select(x => x.UInt16 == 1); - - var stages = Translate(collection, queryable); - if (linqProvider == LinqProvider.V2) - { - AssertStages(stages, "{ $project : { __fld0 : { $eq : ['$UInt16', 1] }, _id : 0 } }"); - } - else - { - AssertStages(stages, "{ $project : { _v : { $eq : ['$UInt16', 1] }, _id : 0 } }"); - } - - var results = queryable.ToList(); - results.Should().Equal(true, false, false); - } - - [Theory] - [ParameterAttributeData] - public void Select_with_UInt32_should_work( - [Values(LinqProvider.V2, LinqProvider.V3)] LinqProvider linqProvider) - { - var collection = CreateCollection(linqProvider); - - var queryable = collection.AsQueryable() - .Select(x => x.UInt32 == 1); - - var stages = Translate(collection, queryable); - if (linqProvider == LinqProvider.V2) - { - AssertStages(stages, "{ $project : { __fld0 : { $eq : ['$UInt32', { $numberLong : 1 }] }, _id : 0 } }"); - } - else - { - AssertStages(stages, "{ $project : { _v : { $eq : ['$UInt32', 1] }, _id : 0 } }"); - } - - var results = queryable.ToList(); - results.Should().Equal(true, false, false); - } - - [Theory] - [ParameterAttributeData] - public void Select_with_UInt64_should_work( - [Values(LinqProvider.V2, LinqProvider.V3)] LinqProvider linqProvider) - { - var collection = CreateCollection(linqProvider); - - var queryable = collection.AsQueryable() - .Select(x => x.UInt64 == 1); - - var stages = Translate(collection, queryable); - if (linqProvider == LinqProvider.V2) - { - AssertStages(stages, "{ $project : { __fld0 : { $eq : ['$UInt64', { $numberLong : 1 }] }, _id : 0 } }"); - } - else - { - AssertStages(stages, "{ $project : { _v : { $eq : ['$UInt64', { $numberLong : 1 }] }, _id : 0 } }"); - } - - var results = queryable.ToList(); - results.Should().Equal(true, false, false); - } - - [Theory] - [InlineData((byte)1, "{ $project : { __fld0 : { $eq : ['$NullableByte', 1] }, _id : 0 } }", new[] { true, false, false }, LinqProvider.V2)] - [InlineData((byte)1, "{ $project : { _v : { $eq : ['$NullableByte', 1] }, _id : 0 } }", new[] { true, false, false }, LinqProvider.V3)] - [InlineData(null, "{ $project : { __fld0 : { $eq : ['$NullableByte', null] }, _id : 0 } }", new[] { false, false, true }, LinqProvider.V2)] - [InlineData(null, "{ $project : { _v : { $eq : ['$NullableByte', null] }, _id : 0 } }", new[] { false, false, true }, LinqProvider.V3)] - public void Select_with_nullable_byte_should_work(byte? value, string expectedStage, bool[] expectedResults, LinqProvider linqProvider) - { - var collection = CreateCollection(linqProvider); - - var queryable = collection.AsQueryable() - .Select(x => x.NullableByte == value); - - var stages = Translate(collection, queryable); - AssertStages(stages, expectedStage); - - var results = queryable.ToList(); - results.Should().Equal(expectedResults); - } - - [Theory] - [InlineData('a', "{ $project : { __fld0 : { $eq : ['$NullableChar', 97] }, _id : 0 } }", new[] { true, false, false }, LinqProvider.V2)] - [InlineData('a', "{ $project : { _v : { $eq : ['$NullableChar', 97] }, _id : 0 } }", new[] { true, false, false }, LinqProvider.V3)] - [InlineData(null, "{ $project : { __fld0 : { $eq : ['$NullableChar', null] }, _id : 0 } }", new[] { false, false, true }, LinqProvider.V2)] - [InlineData(null, "{ $project : { _v : { $eq : ['$NullableChar', null] }, _id : 0 } }", new[] { false, false, true }, LinqProvider.V3)] - public void Select_with_nullable_char_should_work(char? value, string expectedStage, bool[] expectedResults, LinqProvider linqProvider) - { - var collection = CreateCollection(linqProvider); - - var queryable = collection.AsQueryable() - .Select(x => x.NullableChar == value); - - var stages = Translate(collection, queryable); - AssertStages(stages, expectedStage); - - var results = queryable.ToList(); - results.Should().Equal(expectedResults); - } - - [Theory] - [InlineData('a', "{ $project : { __fld0 : { $eq : ['$NullableCharWithStringRepresentation', 97] }, _id : 0 } }", new[] { false, false, false }, LinqProvider.V2)] // note: LINQ2 translation is wrong - [InlineData('a', "{ $project : { _v : { $eq : ['$NullableCharWithStringRepresentation', 'a'] }, _id : 0 } }", new[] { true, false, false }, LinqProvider.V3)] - [InlineData(null, "{ $project : { __fld0 : { $eq : ['$NullableCharWithStringRepresentation', null] }, _id : 0 } }", new[] { false, false, true }, LinqProvider.V2)] - [InlineData(null, "{ $project : { _v : { $eq : ['$NullableCharWithStringRepresentation', null] }, _id : 0 } }", new[] { false, false, true }, LinqProvider.V3)] - public void Select_with_nullable_char_with_string_representation_should_work(char? value, string expectedStage, bool[] expectedResults, LinqProvider linqProvider) - { - var collection = CreateCollection(linqProvider); - - var queryable = collection.AsQueryable() - .Select(x => x.NullableCharWithStringRepresentation == value); - - var stages = Translate(collection, queryable); - AssertStages(stages, expectedStage); - - var results = queryable.ToList(); - results.Should().Equal(expectedResults); - } - - [Theory] - [InlineData(1, "{ $project : { __fld0 : { $eq : ['$NullableDecimal', { $numberDecimal : '1' }] }, _id : 0 } }", new[] { false, false, false }, LinqProvider.V2)] // note: LINQ2 translation is wrong - [InlineData(1, "{ $project : { _v : { $eq : ['$NullableDecimal', '1'] }, _id : 0 } }", new[] { true, false, false }, LinqProvider.V3)] - [InlineData(null, "{ $project : { __fld0 : { $eq : ['$NullableDecimal', null] }, _id : 0 } }", new[] { false, false, true }, LinqProvider.V2)] - [InlineData(null, "{ $project : { _v : { $eq : ['$NullableDecimal', null] }, _id : 0 } }", new[] { false, false, true }, LinqProvider.V3)] - public void Select_with_nullable_decimal_should_work(int? value, string expectedStage, bool[] expectedResults, LinqProvider linqProvider) - { - var collection = CreateCollection(linqProvider); - - var queryable = collection.AsQueryable() - .Select(x => x.NullableDecimal == value); - - var stages = Translate(collection, queryable); - AssertStages(stages, expectedStage); - - var results = queryable.ToList(); - results.Should().Equal(expectedResults); - } - - [Theory] - [InlineData(1, "{ $project : { __fld0 : { $eq : ['$NullableDecimalWithNumericRepresentation', { $numberDecimal : '1' }] }, _id : 0 } }", new[] { true, false, false }, LinqProvider.V2)] - [InlineData(1, "{ $project : { _v : { $eq : ['$NullableDecimalWithNumericRepresentation', { $numberDecimal : '1' }] }, _id : 0 } }", new[] { true, false, false }, LinqProvider.V3)] - [InlineData(null, "{ $project : { __fld0 : { $eq : ['$NullableDecimalWithNumericRepresentation', null] }, _id : 0 } }", new[] { false, false, true }, LinqProvider.V2)] - [InlineData(null, "{ $project : { _v : { $eq : ['$NullableDecimalWithNumericRepresentation', null] }, _id : 0 } }", new[] { false, false, true }, LinqProvider.V3)] - public void Select_with_nullable_decimal_with_numeric_representation_should_work(int? value, string expectedStage, bool[] expectedResults, LinqProvider linqProvider) - { - var collection = CreateCollection(linqProvider); - - var queryable = collection.AsQueryable() - .Select(x => x.NullableDecimalWithNumericRepresentation == value); - - var stages = Translate(collection, queryable); - AssertStages(stages, expectedStage); - - var results = queryable.ToList(); - results.Should().Equal(expectedResults); - } - - [Theory] - [InlineData(1, "{ $project : { __fld0 : { $eq : ['$NullableDecimal128', { $numberDecimal : '1' }] }, _id : 0 } }", new[] { false, false, false }, LinqProvider.V2)] // note: LINQ2 translation is wrong - [InlineData(1, "{ $project : { _v : { $eq : ['$NullableDecimal128', '1'] }, _id : 0 } }", new[] { true, false, false }, LinqProvider.V3)] - [InlineData(null, "{ $project : { __fld0 : { $eq : ['$NullableDecimal128', null] }, _id : 0 } }", new[] { false, false, true }, LinqProvider.V2)] - [InlineData(null, "{ $project : { _v : { $eq : ['$NullableDecimal128', null] }, _id : 0 } }", new[] { false, false, true }, LinqProvider.V3)] - public void Select_with_nullable_Decimal128_should_work(int? value, string expectedStage, bool[] expectedResults, LinqProvider linqProvider) - { - var collection = CreateCollection(linqProvider); - - var queryable = collection.AsQueryable() - .Select(x => x.NullableDecimal128 == value); - - var stages = Translate(collection, queryable); - AssertStages(stages, expectedStage); - - var results = queryable.ToList(); - results.Should().Equal(expectedResults); - } - - [Theory] - [InlineData(1, "{ $project : { __fld0 : { $eq : ['$NullableDecimal128WithNumericRepresentation', { $numberDecimal : '1' }] }, _id : 0 } }", new[] { true, false, false }, LinqProvider.V2)] - [InlineData(1, "{ $project : { _v : { $eq : ['$NullableDecimal128WithNumericRepresentation', { $numberDecimal : '1' }] }, _id : 0 } }", new[] { true, false, false }, LinqProvider.V3)] - [InlineData(null, "{ $project : { __fld0 : { $eq : ['$NullableDecimal128WithNumericRepresentation', null] }, _id : 0 } }", new[] { false, false, true }, LinqProvider.V2)] - [InlineData(null, "{ $project : { _v : { $eq : ['$NullableDecimal128WithNumericRepresentation', null] }, _id : 0 } }", new[] { false, false, true }, LinqProvider.V3)] - public void Select_with_nullable_Decimal128_with_numeric_representation_should_work(int? value, string expectedStage, bool[] expectedResults, LinqProvider linqProvider) - { - var collection = CreateCollection(linqProvider); - - var queryable = collection.AsQueryable() - .Select(x => x.NullableDecimal128WithNumericRepresentation == value); - - var stages = Translate(collection, queryable); - AssertStages(stages, expectedStage); - - var results = queryable.ToList(); - results.Should().Equal(expectedResults); - } - - [Theory] - [InlineData((double)1.0, "{ $project : { __fld0 : { $eq : ['$NullableDouble', 1.0] }, _id : 0 } }", new[] { true, false, false }, LinqProvider.V2)] - [InlineData((double)1.0, "{ $project : { _v : { $eq : ['$NullableDouble', 1.0] }, _id : 0 } }", new[] { true, false, false }, LinqProvider.V3)] - [InlineData(null, "{ $project : { __fld0 : { $eq : ['$NullableDouble', null] }, _id : 0 } }", new[] { false, false, true }, LinqProvider.V2)] - [InlineData(null, "{ $project : { _v : { $eq : ['$NullableDouble', null] }, _id : 0 } }", new[] { false, false, true }, LinqProvider.V3)] - public void Select_with_nullable_Double_should_work(double? value, string expectedStage, bool[] expectedResults, LinqProvider linqProvider) - { - var collection = CreateCollection(linqProvider); - - var queryable = collection.AsQueryable() - .Select(x => x.NullableDouble == value); - - var stages = Translate(collection, queryable); - AssertStages(stages, expectedStage); - - var results = queryable.ToList(); - results.Should().Equal(expectedResults); - } - - [Theory] - [InlineData((short)1, "{ $project : { __fld0 : { $eq : ['$NullableInt16', 1] }, _id : 0 } }", new[] { true, false, false }, LinqProvider.V2)] - [InlineData((short)1, "{ $project : { _v : { $eq : ['$NullableInt16', 1] }, _id : 0 } }", new[] { true, false, false }, LinqProvider.V3)] - [InlineData(null, "{ $project : { __fld0 : { $eq : ['$NullableInt16', null] }, _id : 0 } }", new[] { false, false, true }, LinqProvider.V2)] - [InlineData(null, "{ $project : { _v : { $eq : ['$NullableInt16', null] }, _id : 0 } }", new[] { false, false, true }, LinqProvider.V3)] - public void Select_with_nullable_Int16_should_work(short? value, string expectedStage, bool[] expectedResults, LinqProvider linqProvider) - { - var collection = CreateCollection(linqProvider); - - var queryable = collection.AsQueryable() - .Select(x => x.NullableInt16 == value); - - var stages = Translate(collection, queryable); - AssertStages(stages, expectedStage); - - var results = queryable.ToList(); - results.Should().Equal(expectedResults); - } - - [Theory] - [InlineData(1, "{ $project : { __fld0 : { $eq : ['$NullableInt32', 1] }, _id : 0 } }", new[] { true, false, false }, LinqProvider.V2)] - [InlineData(1, "{ $project : { _v : { $eq : ['$NullableInt32', 1] }, _id : 0 } }", new[] { true, false, false }, LinqProvider.V3)] - [InlineData(null, "{ $project : { __fld0 : { $eq : ['$NullableInt32', null] }, _id : 0 } }", new[] { false, false, true }, LinqProvider.V2)] - [InlineData(null, "{ $project : { _v : { $eq : ['$NullableInt32', null] }, _id : 0 } }", new[] { false, false, true }, LinqProvider.V3)] - public void Select_with_nullable_Int32_should_work(int? value, string expectedStage, bool[] expectedResults, LinqProvider linqProvider) - { - var collection = CreateCollection(linqProvider); - - var queryable = collection.AsQueryable() - .Select(x => x.NullableInt32 == value); - - var stages = Translate(collection, queryable); - AssertStages(stages, expectedStage); - - var results = queryable.ToList(); - results.Should().Equal(expectedResults); - } - - [Theory] - [InlineData((long)1, "{ $project : { __fld0 : { $eq : ['$NullableInt64', { $numberLong : 1 }] }, _id : 0 } }", new[] { true, false, false }, LinqProvider.V2)] - [InlineData((long)1, "{ $project : { _v : { $eq : ['$NullableInt64', { $numberLong : 1 }] }, _id : 0 } }", new[] { true, false, false }, LinqProvider.V3)] - [InlineData(null, "{ $project : { __fld0 : { $eq : ['$NullableInt64', null] }, _id : 0 } }", new[] { false, false, true }, LinqProvider.V2)] - [InlineData(null, "{ $project : { _v : { $eq : ['$NullableInt64', null] }, _id : 0 } }", new[] { false, false, true }, LinqProvider.V3)] - public void Select_with_nullable_Int64_should_work(long? value, string expectedStage, bool[] expectedResults, LinqProvider linqProvider) - { - var collection = CreateCollection(linqProvider); - - var queryable = collection.AsQueryable() - .Select(x => x.NullableInt64 == value); - - var stages = Translate(collection, queryable); - AssertStages(stages, expectedStage); - - var results = queryable.ToList(); - results.Should().Equal(expectedResults); - } - - [Theory] - [InlineData((sbyte)1, "{ $project : { __fld0 : { $eq : ['$NullableSByte', 1] }, _id : 0 } }", new[] { true, false, false }, LinqProvider.V2)] - [InlineData((sbyte)1, "{ $project : { _v : { $eq : ['$NullableSByte', 1] }, _id : 0 } }", new[] { true, false, false }, LinqProvider.V3)] - [InlineData(null, "{ $project : { __fld0 : { $eq : ['$NullableSByte', null] }, _id : 0 } }", new[] { false, false, true }, LinqProvider.V2)] - [InlineData(null, "{ $project : { _v : { $eq : ['$NullableSByte', null] }, _id : 0 } }", new[] { false, false, true }, LinqProvider.V3)] - public void Select_with_nullable_SByte_should_work(sbyte? value, string expectedStage, bool[] expectedResults, LinqProvider linqProvider) - { - var collection = CreateCollection(linqProvider); - - var queryable = collection.AsQueryable() - .Select(x => x.NullableSByte == value); - - var stages = Translate(collection, queryable); - AssertStages(stages, expectedStage); - - var results = queryable.ToList(); - results.Should().Equal(expectedResults); - } - - [Theory] - [InlineData(1.0F, "{ $project : { __fld0 : { $eq : ['$NullableSingle', 1.0] }, _id : 0 } }", new[] { true, false, false }, LinqProvider.V2)] - [InlineData(1.0F, "{ $project : { _v : { $eq : ['$NullableSingle', 1.0] }, _id : 0 } }", new[] { true, false, false }, LinqProvider.V3)] - [InlineData(null, "{ $project : { __fld0 : { $eq : ['$NullableSingle', null] }, _id : 0 } }", new[] { false, false, true }, LinqProvider.V2)] - [InlineData(null, "{ $project : { _v : { $eq : ['$NullableSingle', null] }, _id : 0 } }", new[] { false, false, true }, LinqProvider.V3)] - public void Select_with_nullable_Single_should_work(float? value, string expectedStage, bool[] expectedResults, LinqProvider linqProvider) - { - var collection = CreateCollection(linqProvider); - - var queryable = collection.AsQueryable() - .Select(x => x.NullableSingle == value); - - var stages = Translate(collection, queryable); - AssertStages(stages, expectedStage); - - var results = queryable.ToList(); - results.Should().Equal(expectedResults); - } - - [Theory] - [InlineData(1.0, "{ $project : { __fld0 : { $eq : ['$NullableSingle', 1.0] }, _id : 0 } }", new[] { true, false, false }, LinqProvider.V2)] - [InlineData(1.0, "{ $project : { _v : { $eq : ['$NullableSingle', 1.0] }, _id : 0 } }", new[] { true, false, false }, LinqProvider.V3)] - [InlineData(null, "{ $project : { __fld0 : { $eq : ['$NullableSingle', null] }, _id : 0 } }", new[] { false, false, true }, LinqProvider.V2)] - [InlineData(null, "{ $project : { _v : { $eq : ['$NullableSingle', null] }, _id : 0 } }", new[] { false, false, true }, LinqProvider.V3)] - public void Select_with_nullable_Single_compared_to_Double_value_should_work(double? value, string expectedStage, bool[] expectedResults, LinqProvider linqProvider) - { - var collection = CreateCollection(linqProvider); - - var queryable = collection.AsQueryable() - .Select(x => x.NullableSingle == value); - - var stages = Translate(collection, queryable); - AssertStages(stages, expectedStage); - - var results = queryable.ToList(); - results.Should().Equal(expectedResults); - } - - [Theory] - [ParameterAttributeData] - public void Select_with_nullable_Single_compared_to_Double_field_should_work( - [Values(LinqProvider.V2, LinqProvider.V3)] LinqProvider linqProvider) - { - var collection = CreateCollection(linqProvider); - - var queryable = collection.AsQueryable() - .Select(x => x.NullableSingle == x.NullableDouble); - - var stages = Translate(collection, queryable); - if (linqProvider == LinqProvider.V2) - { - AssertStages(stages, "{ $project : { __fld0 : { $eq : ['$NullableSingle', '$NullableDouble'] }, _id : 0 } }"); - } - else - { - AssertStages(stages, "{ $project : { _v : { $eq : ['$NullableSingle', '$NullableDouble'] }, _id : 0 } }"); - } - - var results = queryable.ToList(); - results.Should().Equal(true, true, true); - } - - [Theory] - [InlineData((ushort)1, "{ $project : { __fld0 : { $eq : ['$NullableUInt16', 1] }, _id : 0 } }", new[] { true, false, false }, LinqProvider.V2)] - [InlineData((ushort)1, "{ $project : { _v : { $eq : ['$NullableUInt16', 1] }, _id : 0 } }", new[] { true, false, false }, LinqProvider.V3)] - [InlineData(null, "{ $project : { __fld0 : { $eq : ['$NullableUInt16', null] }, _id : 0 } }", new[] { false, false, true }, LinqProvider.V2)] - [InlineData(null, "{ $project : { _v : { $eq : ['$NullableUInt16', null] }, _id : 0 } }", new[] { false, false, true }, LinqProvider.V3)] - public void Select_with_nullable_UInt16_should_work(ushort? value, string expectedStage, bool[] expectedResults, LinqProvider linqProvider) - { - var collection = CreateCollection(linqProvider); - - var queryable = collection.AsQueryable() - .Select(x => x.NullableUInt16 == value); - - var stages = Translate(collection, queryable); - AssertStages(stages, expectedStage); - - var results = queryable.ToList(); - results.Should().Equal(expectedResults); - } - - [Theory] - [InlineData(1U, "{ $project : { __fld0 : { $eq : ['$NullableUInt32', { $numberLong : 1 }] }, _id : 0 } }", new[] { true, false, false }, LinqProvider.V2)] - [InlineData(1U, "{ $project : { _v : { $eq : ['$NullableUInt32', 1] }, _id : 0 } }", new[] { true, false, false }, LinqProvider.V3)] - [InlineData(null, "{ $project : { __fld0 : { $eq : ['$NullableUInt32', null] }, _id : 0 } }", new[] { false, false, true }, LinqProvider.V2)] - [InlineData(null, "{ $project : { _v : { $eq : ['$NullableUInt32', null] }, _id : 0 } }", new[] { false, false, true }, LinqProvider.V3)] - public void Select_with_nullable_UInt32_should_work(uint? value, string expectedStage, bool[] expectedResults, LinqProvider linqProvider) - { - var collection = CreateCollection(linqProvider); - - var queryable = collection.AsQueryable() - .Select(x => x.NullableUInt32 == value); - - var stages = Translate(collection, queryable); - AssertStages(stages, expectedStage); - - var results = queryable.ToList(); - results.Should().Equal(expectedResults); - } - - [Theory] - [InlineData(1UL, "{ $project : { __fld0 : { $eq : ['$NullableUInt64', { $numberLong : 1 }] }, _id : 0 } }", new[] { true, false, false }, LinqProvider.V2)] - [InlineData(1UL, "{ $project : { _v : { $eq : ['$NullableUInt64', { $numberLong : 1 }] }, _id : 0 } }", new[] { true, false, false }, LinqProvider.V3)] - [InlineData(null, "{ $project : { __fld0 : { $eq : ['$NullableUInt64', null] }, _id : 0 } }", new[] { false, false, true }, LinqProvider.V2)] - [InlineData(null, "{ $project : { _v : { $eq : ['$NullableUInt64', null] }, _id : 0 } }", new[] { false, false, true }, LinqProvider.V3)] - public void Select_with_nullable_UInt64_should_work(ulong? value, string expectedStage, bool[] expectedResults, LinqProvider linqProvider) - { - var collection = CreateCollection(linqProvider); - - var queryable = collection.AsQueryable() - .Select(x => x.NullableUInt64 == value); - - var stages = Translate(collection, queryable); - AssertStages(stages, expectedStage); - - var results = queryable.ToList(); - results.Should().Equal(expectedResults); - } - - private IMongoCollection CreateCollection(LinqProvider linqProvider) - { - var collection = GetCollection("test", linqProvider); - - CreateCollection( - collection, - new TestObject - { - Id = 1, - - Byte = 1, - Char = 'a', - CharWithStringRepresentation = 'a', - Decimal = 1M, - DecimalWithNumericRepresentation = 1M, - Decimal128 = 1M, - Decimal128WithNumericRepresentation = 1M, - Double = 1.0, - Int16 = 1, - Int32 = 1, - Int64 = 1, - SByte = 1, - Single = 1, - UInt16 = 1, - UInt32 = 1, - UInt64 = 1, - - NullableByte = 1, - NullableChar = 'a', - NullableCharWithStringRepresentation = 'a', - NullableDecimal = 1M, - NullableDecimalWithNumericRepresentation = 1M, - NullableDecimal128 = 1M, - NullableDecimal128WithNumericRepresentation = 1M, - NullableDouble = 1.0, - NullableInt16 = 1, - NullableInt32 = 1, - NullableInt64 = 1, - NullableSByte = 1, - NullableSingle = 1, - NullableUInt16 = 1, - NullableUInt32 = 1, - NullableUInt64 = 1, - }, - new TestObject - { - Id = 2, - - Byte = 2, - Char = 'b', - CharWithStringRepresentation = 'b', - Decimal = 2M, - DecimalWithNumericRepresentation = 2M, - Decimal128 = 2M, - Decimal128WithNumericRepresentation = 2M, - Double = 2.0, - Int16 = 2, - Int32 = 2, - Int64 = 2, - SByte = 2, - Single = 2, - UInt16 = 2, - UInt32 = 2, - UInt64 = 2, - - NullableByte = 2, - NullableChar = 'b', - NullableCharWithStringRepresentation = 'b', - NullableDecimal = 2M, - NullableDecimalWithNumericRepresentation = 2M, - NullableDecimal128 = 2M, - NullableDecimal128WithNumericRepresentation = 2M, - NullableDouble = 2.0, - NullableInt16 = 2, - NullableInt32 = 2, - NullableInt64 = 2, - NullableSByte = 2, - NullableSingle = 2, - NullableUInt16 = 2, - NullableUInt32 = 2, - NullableUInt64 = 2, - }, - new TestObject - { - Id = 3 - }); - - return collection; - } - - private class TestObject - { - public int Id { get; set; } - - public byte Byte { get; set; } - public char Char { get; set; } - [BsonRepresentation(BsonType.String)] public char CharWithStringRepresentation { get; set; } - public decimal Decimal { get; set; } - [BsonRepresentation(BsonType.Decimal128)] public decimal DecimalWithNumericRepresentation { get; set; } - public Decimal128 Decimal128 { get; set; } - [BsonRepresentation(BsonType.Decimal128)] public Decimal128 Decimal128WithNumericRepresentation { get; set; } - public double Double { get; set; } - public short Int16 { get; set; } - public int Int32 { get; set; } - public long Int64 { get; set; } - public sbyte SByte { get; set; } - public float Single { get; set; } - public ushort UInt16 { get; set; } - public uint UInt32 { get; set; } - public ulong UInt64 { get; set; } - - public byte? NullableByte { get; set; } - public char? NullableChar { get; set; } - [BsonRepresentation(BsonType.String)] public char? NullableCharWithStringRepresentation { get; set; } - public decimal? NullableDecimal { get; set; } - [BsonRepresentation(BsonType.Decimal128)] public decimal? NullableDecimalWithNumericRepresentation { get; set; } - public Decimal128? NullableDecimal128 { get; set; } - [BsonRepresentation(BsonType.Decimal128)] public Decimal128? NullableDecimal128WithNumericRepresentation { get; set; } - public double? NullableDouble { get; set; } - public short? NullableInt16 { get; set; } - public int? NullableInt32 { get; set; } - public long? NullableInt64 { get; set; } - public sbyte? NullableSByte { get; set; } - public float? NullableSingle { get; set; } - public ushort? NullableUInt16 { get; set; } - public uint? NullableUInt32 { get; set; } - public ulong? NullableUInt64 { get; set; } - } - } -} diff --git a/tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/Jira/CSharp4596Tests.cs b/tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/Jira/CSharp4596Tests.cs deleted file mode 100644 index c673b505f24..00000000000 --- a/tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/Jira/CSharp4596Tests.cs +++ /dev/null @@ -1,73 +0,0 @@ -/* Copyright 2010-present MongoDB Inc. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -using System; -using FluentAssertions; -using MongoDB.Driver.Core.Misc; -using MongoDB.Driver.Core.TestHelpers.XunitExtensions; -using MongoDB.Driver.Linq; -using MongoDB.Driver.Tests.Linq.Linq3Implementation; -using MongoDB.TestHelpers.XunitExtensions; -using Xunit; - -namespace MongoDB.Driver.Tests.Linq.Linq3ImplementationTests.Jira -{ - public class CSharp4596Tests : Linq3IntegrationTest - { - [Theory] - [ParameterAttributeData] - public void Subtract_DateTimes_should_work( - [Values(LinqProvider.V2, LinqProvider.V3)] LinqProvider linqProvider) - { - RequireServer.Check().Supports(Feature.DateOperatorsNewIn50); - var collection = CreateCollection(linqProvider); - var startTime = new DateTime(2023, 04, 04, 0, 0, 0, DateTimeKind.Utc); - - var queryable = collection.AsQueryable() - .Select(record => record.DateTimeUtc.Subtract(startTime, DateTimeUnit.Millisecond) / (double)5); - - if (linqProvider == LinqProvider.V2) - { - var exception = Record.Exception(() => Translate(collection, queryable)); - exception.Should().BeOfType(); - } - else - { - var stages = Translate(collection, queryable); - AssertStages( - stages, - "{ $project : { _v : { $divide : [{ $dateDiff : { startDate : ISODate('2023-04-04T00:00:00Z'), endDate : '$DateTimeUtc', unit : 'millisecond' } }, 5.0] }, _id : 0 } }"); - - var results = queryable.ToList(); - results.Should().Equal(200.0); - } - } - - private IMongoCollection CreateCollection(LinqProvider linqProvider) - { - var collection = GetCollection("test", linqProvider); - CreateCollection( - collection, - new C { Id = 1, DateTimeUtc = new DateTime(2023, 04, 04, 0, 0, 1, DateTimeKind.Utc) }); - return collection; - } - - private class C - { - public int Id { get; set; } - public DateTime DateTimeUtc { get; set; } - } - } -} diff --git a/tests/MongoDB.Driver.Tests/Linq/Linq3ImplementationWithLinq2Tests/MongoQueryableIntComparedToDoubleWithStringRepresentationTests.cs b/tests/MongoDB.Driver.Tests/Linq/Linq3ImplementationWithLinq2Tests/MongoQueryableIntComparedToDoubleWithStringRepresentationTests.cs index 0b9592374fa..43d5e21914c 100644 --- a/tests/MongoDB.Driver.Tests/Linq/Linq3ImplementationWithLinq2Tests/MongoQueryableIntComparedToDoubleWithStringRepresentationTests.cs +++ b/tests/MongoDB.Driver.Tests/Linq/Linq3ImplementationWithLinq2Tests/MongoQueryableIntComparedToDoubleWithStringRepresentationTests.cs @@ -17,7 +17,6 @@ using FluentAssertions; using MongoDB.Bson; using MongoDB.Bson.Serialization.Attributes; -using MongoDB.Driver.Linq; using MongoDB.Driver.Linq.Linq3Implementation; using MongoDB.Driver.Linq.Linq3Implementation.Translators.ExpressionToExecutableQueryTranslators; using Xunit; @@ -44,28 +43,18 @@ public class C } [Theory] - [InlineData(1.0, "{ \"I\" : \"1\" }")] - [InlineData(1.5, "throws")] + [InlineData(1.5, "{ \"I\" : \"1.5\" }")] public void Where_operator_equal_should_render_correctly(double value, string expectedFilter) { var subject = __collection.AsQueryable(); var queryable = subject.Where(x => x.I == value); - if (expectedFilter == "throws") - { - var exception = Record.Exception(() => AssertFilter(queryable, expectedFilter)); - exception.Should().BeOfType(); - exception.Message.Should().Contain("The constant 1.5 could not be converted to Int32 in order to be serialized using the proper serializer"); - } - else - { - AssertFilter(queryable, expectedFilter); - } + AssertFilter(queryable, expectedFilter); } [Theory] - [InlineData(1.0, "{ \"I\" : { \"$gt\" : \"1\" } }")] + [InlineData(1.5, "{ \"I\" : { \"$gt\" : \"1.5\" } }")] public void Where_operator_greater_than_should_render_correctly(double value, string expectedFilter) { var subject = __collection.AsQueryable(); @@ -76,7 +65,7 @@ public void Where_operator_greater_than_should_render_correctly(double value, st } [Theory] - [InlineData(1.0, "{ \"I\" : { \"$gte\" : \"1\" } }")] + [InlineData(1.5, "{ \"I\" : { \"$gte\" : \"1.5\" } }")] public void Where_operator_greater_than_or_equal_should_render_correctly(double value, string expectedFilter) { var subject = __collection.AsQueryable(); @@ -87,7 +76,7 @@ public void Where_operator_greater_than_or_equal_should_render_correctly(double } [Theory] - [InlineData(1.0, "{ \"I\" : { \"$lt\" : \"1\" } }")] + [InlineData(1.5, "{ \"I\" : { \"$lt\" : \"1.5\" } }")] public void Where_operator_less_than_should_render_correctly(double value, string expectedFilter) { var subject = __collection.AsQueryable(); @@ -98,7 +87,7 @@ public void Where_operator_less_than_should_render_correctly(double value, strin } [Theory] - [InlineData(1.0, "{ \"I\" : { \"$lte\" : \"1\" } }")] + [InlineData(1.5, "{ \"I\" : { \"$lte\" : \"1.5\" } }")] public void Where_operator_less_than_or_equal_should_render_correctly(double value, string expectedFilter) { var subject = __collection.AsQueryable(); @@ -109,7 +98,7 @@ public void Where_operator_less_than_or_equal_should_render_correctly(double val } [Theory] - [InlineData(1.0, "{ \"I\" : { \"$ne\" : \"1\" } }")] + [InlineData(1.5, "{ \"I\" : { \"$ne\" : \"1.5\" } }")] public void Where_operator_not_equal_should_render_correctly(double value, string expectedFilter) { var subject = __collection.AsQueryable();