diff --git a/LiteDB.Tests/Issues/Issue2487_Tests.cs b/LiteDB.Tests/Issues/Issue2487_Tests.cs new file mode 100644 index 000000000..cc3109f03 --- /dev/null +++ b/LiteDB.Tests/Issues/Issue2487_Tests.cs @@ -0,0 +1,45 @@ +using FluentAssertions; + +using System.Diagnostics; + +using Xunit; + +namespace LiteDB.Tests.Issues; + +public class Issue2487_tests +{ + private class DataClass + { + [BsonId] + public int Id { get; set; } + + public string Foo { get; set; } + + public string Bar { get; set; } + } + + [Fact] + public void Test_Contains_EmptyStrings() + { + using var engine = new ConnectionString(":memory:").CreateEngine(); + + using var db = new LiteDatabase(engine); + var collection = db.GetCollection("data"); + + collection.Insert(new DataClass { Foo = "bar", Bar = "abc" }); + collection.Insert(new DataClass { Foo = " ", Bar = "def" }); + collection.Insert(new DataClass { Foo = "fo bar", Bar = "def" }); + collection.Insert(new DataClass { Foo = "", Bar = "def" }); + collection.Insert(new DataClass { Foo = null, Bar = "def" }); + + var containsAction = () => collection.FindOne(x => x.Foo.Contains(" ")); + containsAction.Should().NotThrow(); + + var def = containsAction(); + def.Should().NotBeNull(); + def.Bar.Should().Be("def"); + + var shouldExecute = () => engine.Query("data", Query.All(Query.Contains("Foo", " "))); + shouldExecute.Should().NotThrow(); + } +} \ No newline at end of file diff --git a/LiteDB.Tests/LiteDB.Tests.csproj b/LiteDB.Tests/LiteDB.Tests.csproj index 2fe8c4f08..831a78701 100644 --- a/LiteDB.Tests/LiteDB.Tests.csproj +++ b/LiteDB.Tests/LiteDB.Tests.csproj @@ -9,6 +9,8 @@ en-US false 1701;1702;1705;1591;0618 + True + ..\LiteDB\LiteDB.snk diff --git a/LiteDB/Client/Structures/Query.cs b/LiteDB/Client/Structures/Query.cs index 28fd6a70f..9bbd6388e 100644 --- a/LiteDB/Client/Structures/Query.cs +++ b/LiteDB/Client/Structures/Query.cs @@ -1,7 +1,9 @@ using LiteDB.Engine; + using System; using System.Collections.Generic; using System.Linq; + using static LiteDB.Constants; namespace LiteDB @@ -83,7 +85,6 @@ public static BsonExpression GT(string field, BsonValue value) if (field.IsNullOrWhiteSpace()) throw new ArgumentNullException(nameof(field)); return BsonExpression.Create($"{field} > {value ?? BsonValue.Null}"); - } /// @@ -123,7 +124,7 @@ public static BsonExpression StartsWith(string field, string value) public static BsonExpression Contains(string field, string value) { if (field.IsNullOrWhiteSpace()) throw new ArgumentNullException(nameof(field)); - if (value.IsNullOrWhiteSpace()) throw new ArgumentNullException(nameof(value)); + if (value.IsNullOrEmpty()) throw new ArgumentNullException(nameof(value)); return BsonExpression.Create($"{field} LIKE {(new BsonValue("%" + value + "%"))}"); } diff --git a/LiteDB/Utils/Constants.cs b/LiteDB/Utils/Constants.cs index 91c480f30..93458193d 100644 --- a/LiteDB/Utils/Constants.cs +++ b/LiteDB/Utils/Constants.cs @@ -1,11 +1,12 @@ using LiteDB.Engine; + using System; using System.Diagnostics; using System.Runtime.CompilerServices; using System.Threading; +[assembly: InternalsVisibleTo("LiteDB.Tests, PublicKey=002400000480000094000000060200000024000052534131000400000100010029e66990e22110ce40a7197e37f8f82df3332c399e696df7f27d09e14ee590ac2dda735d4777fe554c427540bde93b14d3d26c04731c963383dcaa18859c8cbcd4a1a9c394d1204f474c2ab6f23a2eaadf81eb8a7a3d3cc73658868b0302163b92a2614ca050ab703be33c3e1d76f55b11f4f87cb73558f3aa69c1ce726d9ee8")] #if DEBUG -[assembly: InternalsVisibleTo("LiteDB.Tests")] [assembly: InternalsVisibleTo("ConsoleApp1")] #endif @@ -197,4 +198,4 @@ public static void DEBUG(bool conditional, string message = null) } } } -} +} \ No newline at end of file diff --git a/LiteDB/Utils/Extensions/StringExtensions.cs b/LiteDB/Utils/Extensions/StringExtensions.cs index eb777da5e..00ed9b54c 100644 --- a/LiteDB/Utils/Extensions/StringExtensions.cs +++ b/LiteDB/Utils/Extensions/StringExtensions.cs @@ -1,16 +1,25 @@ using System; using System.Collections.Generic; +using System.Runtime.CompilerServices; using System.Security.Cryptography; using System.Text; + using static LiteDB.Constants; namespace LiteDB { internal static class StringExtensions { + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool IsNullOrWhiteSpace(this string str) { - return str == null || str.Trim().Length == 0; + return string.IsNullOrWhiteSpace(str); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool IsNullOrEmpty(this string str) + { + return string.IsNullOrEmpty(str); } /// @@ -28,13 +37,6 @@ public static bool IsWord(this string str) return true; } - public static string TrimToNull(this string str) - { - var v = str.Trim(); - - return v.Length == 0 ? null : v; - } - public static string Sha1(this string value) { var data = Encoding.UTF8.GetBytes(value);