From 3f82eed99136463845e2e3d8e0f5f11252fa7dab Mon Sep 17 00:00:00 2001 From: halgari Date: Tue, 15 Oct 2024 12:19:08 -0600 Subject: [PATCH] Fixed a bug in the key prefix and added a test of failed migration (converting a URI to a ulong) --- .../Internals/KeyPrefix.cs | 2 +- .../Serializer.cs | 27 ++++++++++++----- .../MigrationTests.cs | 30 +++++++++++++++++++ 3 files changed, 51 insertions(+), 8 deletions(-) diff --git a/src/NexusMods.MnemonicDB.Abstractions/Internals/KeyPrefix.cs b/src/NexusMods.MnemonicDB.Abstractions/Internals/KeyPrefix.cs index 7915700..fb1feac 100644 --- a/src/NexusMods.MnemonicDB.Abstractions/Internals/KeyPrefix.cs +++ b/src/NexusMods.MnemonicDB.Abstractions/Internals/KeyPrefix.cs @@ -95,7 +95,7 @@ public bool IsRetract public ValueTag ValueTag { get => (ValueTag)((_lower >> 1) & 0x7F); - init => _lower = (_lower & 0xFF00000000000001) | ((ulong)value << 1); + init => _lower = (_lower & 0xFFFFFFFFFFFFFF01) | ((ulong)value << 1); } /// diff --git a/src/NexusMods.MnemonicDB.Abstractions/Serializer.cs b/src/NexusMods.MnemonicDB.Abstractions/Serializer.cs index bcf67a2..ce331bb 100644 --- a/src/NexusMods.MnemonicDB.Abstractions/Serializer.cs +++ b/src/NexusMods.MnemonicDB.Abstractions/Serializer.cs @@ -403,14 +403,27 @@ public static void ConvertValue(this ValueTag srcTag, ReadOnlySpan { - switch (srcTag, destTag) + try { - case (ValueTag.UInt8, ValueTag.UInt16): - WriteUnmanaged((ushort)MemoryMarshal.Read(srcSpan), destWriter); - break; - - default: - throw new NotSupportedException("Conversion not supported from " + srcTag + " to " + destTag); + switch (srcTag, destTag) + { + case (ValueTag.UInt8, ValueTag.UInt16): + WriteUnmanaged((ushort)MemoryMarshal.Read(srcSpan), destWriter); + break; + case (ValueTag.Utf8, ValueTag.UInt64): + { + var val = srcTag.Read(srcSpan); + WriteUnmanaged(Convert.ToUInt64(val), destWriter); + break; + } + + default: + throw new NotSupportedException("Conversion not supported from " + srcTag + " to " + destTag); + } + } + catch (Exception e) + { + throw new InvalidOperationException($"Failed to convert ({srcTag.Read(srcSpan)}) value from " + srcTag + " to " + destTag, e); } } diff --git a/tests/NexusMods.MnemonicDB.Tests/MigrationTests.cs b/tests/NexusMods.MnemonicDB.Tests/MigrationTests.cs index a3649eb..b6e2c78 100644 --- a/tests/NexusMods.MnemonicDB.Tests/MigrationTests.cs +++ b/tests/NexusMods.MnemonicDB.Tests/MigrationTests.cs @@ -95,4 +95,34 @@ public async Task CanRemoveIndex() Action act = () => Connection.Db.Datoms(Mod.Source, new Uri("http://mod0.com")).ToArray(); act.Should().Throw(); } + + [Fact] + public async Task CanConvertValues() + { + await AddData(); + + var cache = Connection.AttributeCache; + var aid = cache.GetAttributeId(Mod.Description.Id); + cache.IsIndexed(aid).Should().BeFalse(); + + var withIndex = new ULongAttribute(Mod.Description.Id.Namespace, Mod.Description.Id.Name) { IsIndexed = true, IsOptional = false }; + var prevTxId = Connection.Db.BasisTxId; + + await Connection.UpdateSchema(withIndex); + + Connection.Db.BasisTxId.Value.Should().Be(prevTxId.Value + 1); + cache.IsIndexed(cache.GetAttributeId(Mod.Description.Id)).Should().BeTrue(); + + var foundByDocs = Connection.Db.Datoms(withIndex, 0UL).ToArray(); + foundByDocs.Length.Should().Be(10); + } + + [Fact] + public async Task ConvertingValuesIncorrectlyFails() + { + await AddData(); + var withIndex = new ULongAttribute(Mod.Source.Id.Namespace, Mod.Source.Id.Name) { IsIndexed = true, IsOptional = false }; + var act = async () => await Connection.UpdateSchema(withIndex); + await act.Should().ThrowAsync("Converting values for attribute Mod.Source from String to ULong where the source is a URI should fail"); + } }