Skip to content

Commit

Permalink
Add support for on-the-fly document upgrades
Browse files Browse the repository at this point in the history
  • Loading branch information
JKamsker committed Jun 6, 2024
1 parent 5a46966 commit 25b0940
Show file tree
Hide file tree
Showing 5 changed files with 104 additions and 14 deletions.
76 changes: 76 additions & 0 deletions LiteDB.Tests/Database/DocumentUpgrade_Tests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
using FluentAssertions;

using LiteDB.Engine;

using System.IO;

using Xunit;

namespace LiteDB.Tests.Database;

public class DocumentUpgrade_Tests
{
[Fact]
public void DocumentUpgrade_Test()
{
var ms = new MemoryStream();
using (var db = new LiteDatabase(ms))
{
var col = db.GetCollection("col");

col.Insert(new BsonDocument { ["version"] = 1, ["_id"] = 1, ["name"] = "John" });
}

ms.Position = 0;

using (var db = new LiteDatabase(ms))
{
var col = db.GetCollection("col");

col.Count().Should().Be(1);

var doc = col.FindById(1);

doc["version"].AsInt32.Should().Be(1);
doc["name"].AsString.Should().Be("John");
doc["age"].AsInt32.Should().Be(0);
}

ms.Position = 0;

var engine = new LiteEngine(new EngineSettings
{
DataStream = ms,
ReadTransform = ReadTransform
});

using (var db = new LiteDatabase(engine))
{
var col = db.GetCollection("col");

col.Count().Should().Be(1);

var doc = col.FindById(1);

doc["version"].AsInt32.Should().Be(2);
doc["name"].AsString.Should().Be("John");
doc["age"].AsInt32.Should().Be(30);
}
}

private BsonValue ReadTransform(string arg1, BsonValue val)
{
if (!(val is BsonDocument bdoc))
{
return val;
}

if (bdoc.TryGetValue("version", out var version) && version.AsInt32 == 1)
{
bdoc["version"] = 2;
bdoc["age"] = 30;
}

return val;
}
}
6 changes: 4 additions & 2 deletions LiteDB/Client/Structures/ConnectionString.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using LiteDB.Engine;
using LiteDB.Engine;
using System;
using System.Collections.Generic;
using System.Globalization;
Expand Down Expand Up @@ -107,7 +107,7 @@ public ConnectionString(string connectionString)
/// <summary>
/// Create ILiteEngine instance according string connection parameters. For now, only Local/Shared are supported
/// </summary>
internal ILiteEngine CreateEngine()
internal ILiteEngine CreateEngine(Action<EngineSettings> engineSettingsAction = null)
{
var settings = new EngineSettings
{
Expand All @@ -120,6 +120,8 @@ internal ILiteEngine CreateEngine()
AutoRebuild = this.AutoRebuild,
};

engineSettingsAction?.Invoke(settings);

// create engine implementation as Connection Type
if (this.Connection == ConnectionType.Direct)
{
Expand Down
12 changes: 6 additions & 6 deletions LiteDB/Document/DataReader/BsonDataReader.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using LiteDB.Engine;
using LiteDB.Engine;
using System;
using System.Collections;
using System.Collections.Generic;
Expand Down Expand Up @@ -56,10 +56,10 @@ internal BsonDataReader(IEnumerable<BsonValue> values, string collection, Engine
if (_source.MoveNext())
{
_hasValues = _isFirst = true;
_current = _source.Current;
_current = _state.ReadTransform(_collection, _source.Current);
}
}
catch(Exception ex)
catch (Exception ex)
{
_state.Handle(ex);
throw;
Expand Down Expand Up @@ -102,10 +102,10 @@ public bool Read()
try
{
var read = _source.MoveNext(); // can throw any error here
_current = _source.Current;
_current = _state.ReadTransform(_collection, _source.Current);
return read;
}
catch(Exception ex)
catch (Exception ex)
{
_state.Handle(ex);
throw ex;
Expand All @@ -117,7 +117,7 @@ public bool Read()
}
}
}

public BsonValue this[string field]
{
get
Expand Down
8 changes: 7 additions & 1 deletion LiteDB/Engine/EngineSettings.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.ComponentModel;
Expand All @@ -7,6 +7,7 @@
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;

using static LiteDB.Constants;

namespace LiteDB.Engine
Expand Down Expand Up @@ -66,6 +67,11 @@ public class EngineSettings
/// </summary>
public bool Upgrade { get; set; } = false;

/// <summary>
/// Is used to transform a <see cref="BsonValue"/> from the database on read. This can be used to upgrade data from older versions.
/// </summary>
public Func<string, BsonValue, BsonValue> ReadTransform { get; set; }

/// <summary>
/// Create new IStreamFactory for datafile
/// </summary>
Expand Down
16 changes: 11 additions & 5 deletions LiteDB/Engine/EngineState.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
Expand All @@ -9,7 +9,6 @@

using static LiteDB.Constants;


namespace LiteDB.Engine
{
internal class EngineState
Expand All @@ -25,7 +24,7 @@ internal class EngineState
#endif

public EngineState(LiteEngine engine, EngineSettings settings)
{
{
_engine = engine;
_settings = settings;
}
Expand All @@ -39,7 +38,7 @@ public bool Handle(Exception ex)
{
LOG(ex.Message, "ERROR");

if (ex is IOException ||
if (ex is IOException ||
(ex is LiteException lex && lex.ErrorCode == LiteException.INVALID_DATAFILE_STATE))
{
_exception = ex;
Expand All @@ -51,5 +50,12 @@ public bool Handle(Exception ex)

return true;
}

public BsonValue ReadTransform(string collection, BsonValue value)
{
if (_settings?.ReadTransform is null) return value;

return _settings.ReadTransform(collection, value);
}
}
}
}

0 comments on commit 25b0940

Please sign in to comment.