Skip to content

Commit

Permalink
Adjusted the usage of metadata column data in patch expressions. Closes
Browse files Browse the repository at this point in the history
  • Loading branch information
jeremydmiller committed Apr 2, 2024
1 parent 3b58fbc commit 4901af9
Show file tree
Hide file tree
Showing 9 changed files with 142 additions and 11 deletions.
4 changes: 2 additions & 2 deletions src/Marten/Patching/PatchExpression.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public PatchExpression(ISqlFragment filter, DocumentSessionBase session)
{
_session = session;
var storage = _session.StorageFor(typeof(T));
var operation = new PatchOperation(PatchFunction, storage, _patchSet, _session.Serializer);
var operation = new PatchOperation(session, PatchFunction, storage, _patchSet, _session.Serializer);
if (filter != null)
{
operation.Wheres.Add(storage.FilterDocuments(filter, _session));
Expand All @@ -43,7 +43,7 @@ public PatchExpression(Expression<Func<T, bool>> filterExpression, DocumentSessi
{
_session = session;
var storage = _session.StorageFor(typeof(T));
var operation = new PatchOperation(PatchFunction, storage, _patchSet, _session.Serializer);
var operation = new PatchOperation(session, PatchFunction, storage, _patchSet, _session.Serializer);
if (filterExpression != null)
{
operation.ApplyFiltering(_session, filterExpression);
Expand Down
27 changes: 18 additions & 9 deletions src/Marten/Patching/PatchOperation.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System.Collections.Generic;
using System.Linq;
using Marten.Internal.Operations;
using Marten.Internal.Sessions;
using Marten.Internal.Storage;
using Marten.Linq.SqlGeneration;
using Marten.Schema;
Expand All @@ -19,11 +20,14 @@ internal class PatchFragment: IOperationFragment
private readonly ISerializer _serializer;
private readonly IDocumentStorage _storage;
private readonly DbObjectName _function;
private readonly DocumentSessionBase _session;
private readonly List<PatchData> _patchSet;

public PatchFragment(List<PatchData> patchSet, ISerializer serializer, DbObjectName function,
public PatchFragment(DocumentSessionBase session, List<PatchData> patchSet, ISerializer serializer,
DbObjectName function,
IDocumentStorage storage)
{
_session = session;
_patchSet = patchSet;
_patchSet = patchSet;
_serializer = serializer;
Expand Down Expand Up @@ -59,12 +63,16 @@ public void Apply(ICommandBuilder builder)
builder.Append(_function.QualifiedName);
builder.Append("(data, ");
builder.AppendParameter("[" + string.Join(",", patchSetStr.ToArray()) + "]", NpgsqlDbType.Jsonb);
builder.Append("), ");
builder.Append(SchemaConstants.LastModifiedColumn);
builder.Append(" = (now() at time zone 'utc'), ");
builder.Append(SchemaConstants.VersionColumn);
builder.Append(" = ");
builder.AppendParameter(CombGuidIdGeneration.NewGuid());
builder.Append(")");

if (_storage is IHaveMetadataColumns metadata)
{
foreach (var column in metadata.MetadataColumns().Where(x => x.Enabled && x.ShouldUpdatePartials))
{
builder.Append(", ");
column.WriteMetadataInUpdateStatement(builder, _session);
}
}
}

public OperationRole Role()
Expand All @@ -79,8 +87,9 @@ internal class PatchOperation: StatementOperation, NoDataReturnedCall
private readonly IDocumentStorage _storage;
private readonly List<PatchData> _patchSet;

public PatchOperation(DbObjectName function, IDocumentStorage storage, List<PatchData> patchSet , ISerializer serializer):
base(storage, new PatchFragment(patchSet, serializer, function, storage))
public PatchOperation(DocumentSessionBase session, DbObjectName function, IDocumentStorage storage,
List<PatchData> patchSet, ISerializer serializer):
base(storage, new PatchFragment(session, patchSet, serializer, function, storage))
{
_storage = storage;
_patchSet = patchSet;
Expand Down
10 changes: 10 additions & 0 deletions src/Marten/Storage/Metadata/CausationIdColumn.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@
using Marten.Events.Schema;
using Marten.Internal;
using Marten.Internal.CodeGeneration;
using Marten.Internal.Sessions;
using Marten.Schema;
using Marten.Schema.Arguments;
using NpgsqlTypes;
using Weasel.Postgresql;

namespace Marten.Storage.Metadata;

Expand All @@ -19,6 +21,7 @@ internal class CausationIdColumn: MetadataColumn<string>, ISelectableColumn, IEv
public CausationIdColumn(): base(ColumnName, x => x.CausationId)
{
Enabled = false;
ShouldUpdatePartials = true;
}

public void GenerateSelectorCodeSync(GeneratedMethod method, EventGraph graph, int index)
Expand Down Expand Up @@ -58,6 +61,13 @@ internal override UpsertArgument ToArgument()
{
return new CausationIdArgument();
}

public override void WriteMetadataInUpdateStatement(ICommandBuilder builder, DocumentSessionBase session)
{
builder.Append(ColumnName);
builder.Append(" = ");
builder.AppendParameter(session.CausationId);
}
}

internal class CausationIdArgument: UpsertArgument
Expand Down
10 changes: 10 additions & 0 deletions src/Marten/Storage/Metadata/CorrelationIdColumn.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@
using Marten.Events.Schema;
using Marten.Internal;
using Marten.Internal.CodeGeneration;
using Marten.Internal.Sessions;
using Marten.Schema;
using Marten.Schema.Arguments;
using NpgsqlTypes;
using Weasel.Postgresql;

namespace Marten.Storage.Metadata;

Expand All @@ -19,6 +21,7 @@ internal class CorrelationIdColumn: MetadataColumn<string>, ISelectableColumn, I
public CorrelationIdColumn(): base(ColumnName, x => x.CorrelationId)
{
Enabled = false;
ShouldUpdatePartials = true;
}

public void GenerateSelectorCodeSync(GeneratedMethod method, EventGraph graph, int index)
Expand Down Expand Up @@ -58,6 +61,13 @@ internal override UpsertArgument ToArgument()
{
return new CorrelationIdArgument();
}

public override void WriteMetadataInUpdateStatement(ICommandBuilder builder, DocumentSessionBase session)
{
builder.Append(ColumnName);
builder.Append(" = ");
builder.AppendParameter(session.CorrelationId);
}
}

internal class CorrelationIdArgument: UpsertArgument
Expand Down
10 changes: 10 additions & 0 deletions src/Marten/Storage/Metadata/LastModifiedByColumn.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@
using JasperFx.CodeGeneration.Model;
using Marten.Internal;
using Marten.Internal.CodeGeneration;
using Marten.Internal.Sessions;
using Marten.Schema;
using Marten.Schema.Arguments;
using NpgsqlTypes;
using Weasel.Postgresql;

namespace Marten.Storage.Metadata;

Expand All @@ -17,6 +19,7 @@ internal class LastModifiedByColumn: MetadataColumn<string>, ISelectableColumn
public LastModifiedByColumn(): base(ColumnName, x => x.LastModifiedBy)
{
Enabled = false;
ShouldUpdatePartials = true;
}

public void GenerateCode(StorageStyle storageStyle, GeneratedType generatedType, GeneratedMethod async,
Expand All @@ -35,6 +38,13 @@ internal override UpsertArgument ToArgument()
{
return new LastModifiedByArgument();
}

public override void WriteMetadataInUpdateStatement(ICommandBuilder builder, DocumentSessionBase session)
{
builder.Append(ColumnName);
builder.Append(" = ");
builder.AppendParameter(session.LastModifiedBy);
}
}

internal class LastModifiedByArgument: UpsertArgument
Expand Down
10 changes: 10 additions & 0 deletions src/Marten/Storage/Metadata/LastModifiedColumn.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
using JasperFx.CodeGeneration;
using JasperFx.Core.Reflection;
using Marten.Internal.CodeGeneration;
using Marten.Internal.Sessions;
using Marten.Schema;
using Weasel.Postgresql;

namespace Marten.Storage.Metadata;

Expand All @@ -12,6 +14,8 @@ public LastModifiedColumn(): base(SchemaConstants.LastModifiedColumn, x => x.Las
{
DefaultExpression = "(transaction_timestamp())";
Type = "timestamp with time zone";

ShouldUpdatePartials = true;
}

public void GenerateCode(StorageStyle storageStyle, GeneratedType generatedType, GeneratedMethod async,
Expand All @@ -38,4 +42,10 @@ public bool ShouldSelect(DocumentMapping mapping, StorageStyle storageStyle)
{
return Member != null;
}

public override void WriteMetadataInUpdateStatement(ICommandBuilder builder, DocumentSessionBase session)
{
builder.Append(SchemaConstants.LastModifiedColumn);
builder.Append(" = (now() at time zone 'utc')");
}
}
8 changes: 8 additions & 0 deletions src/Marten/Storage/Metadata/MetadataColumn.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
using JasperFx.Core.Reflection;
using Marten.Internal;
using Marten.Internal.CodeGeneration;
using Marten.Internal.Sessions;
using Marten.Linq.Parsing;
using Marten.Schema;
using Marten.Schema.Arguments;
Expand All @@ -35,6 +36,8 @@ protected MetadataColumn(string name, string type, Type dotNetType): base(name,
/// </summary>
public bool Enabled { get; set; } = true;

public bool ShouldUpdatePartials { get; protected set; }

internal abstract Task ApplyAsync(IMartenSession martenSession, DocumentMetadata metadata, int index,
DbDataReader reader, CancellationToken token);

Expand Down Expand Up @@ -88,6 +91,11 @@ protected void setMemberFromReader(GeneratedType generatedType, GeneratedMethod
async.AssignMemberFromReaderAsync(generatedType, index, mapping.DocumentType, Member.Name);
});
}

public virtual void WriteMetadataInUpdateStatement(ICommandBuilder builder, DocumentSessionBase session)
{
throw new NotSupportedException();
}
}

internal abstract class MetadataColumn<T>: MetadataColumn
Expand Down
11 changes: 11 additions & 0 deletions src/Marten/Storage/Metadata/VersionColumn.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
using System;
using JasperFx.CodeGeneration;
using JasperFx.Core;
using Marten.Internal.CodeGeneration;
using Marten.Internal.Sessions;
using Marten.Schema;
using Weasel.Postgresql;

namespace Marten.Storage.Metadata;

Expand All @@ -11,6 +14,7 @@ public VersionColumn(): base(SchemaConstants.VersionColumn, x => x.CurrentVersio
{
AllowNulls = false;
DefaultExpression = "(md5(random()::text || clock_timestamp()::text)::uuid)";
ShouldUpdatePartials = true;
}

public void GenerateCode(StorageStyle storageStyle, GeneratedType generatedType, GeneratedMethod async,
Expand Down Expand Up @@ -48,4 +52,11 @@ public bool ShouldSelect(DocumentMapping mapping, StorageStyle storageStyle)

return storageStyle != StorageStyle.QueryOnly && mapping.UseOptimisticConcurrency;
}

public override void WriteMetadataInUpdateStatement(ICommandBuilder builder, DocumentSessionBase session)
{
builder.Append(SchemaConstants.VersionColumn);
builder.Append(" = ");
builder.AppendParameter(Guid.NewGuid());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
using System;
using System.Threading.Tasks;
using Marten.Patching;
using Marten.Testing.Documents;
using Marten.Testing.Harness;
using Shouldly;
using Xunit;
using Xunit.Abstractions;

namespace PatchingTests.Patching;

public class patching_with_altered_metadata_columns : OneOffConfigurationsContext
{
private readonly ITestOutputHelper _output;

public patching_with_altered_metadata_columns(ITestOutputHelper output)
{
_output = output;
}

[Fact]
public async Task write_and_read_metadata_from_patch()
{
StoreOptions(opts =>
{
opts.Schema.For<Target>().Metadata(m =>
{
m.Version.Enabled = false;
m.LastModified.Enabled = false;
m.CausationId.Enabled = true;
m.CorrelationId.Enabled = true;
m.LastModifiedBy.Enabled = true;

});
});

var target1 = new Target { Color = Colors.Blue, Number = 1 };
var target2 = new Target { Color = Colors.Blue, Number = 1 };
var target3 = new Target { Color = Colors.Blue, Number = 1 };
var target4 = new Target { Color = Colors.Green, Number = 1 };
var target5 = new Target { Color = Colors.Green, Number = 1 };
var target6 = new Target { Color = Colors.Red, Number = 1 };

theSession.Store(target1, target2, target3, target4, target5, target6);
await theSession.SaveChangesAsync();


theSession.CorrelationId = "correlation1";
theSession.CausationId = "causation1";
theSession.LastModifiedBy = "some guy";

theSession.Logger = new TestOutputMartenLogger(_output);
theSession.Patch<Target>(target1.Id).Set(x => x.Number, 2);

await theSession.SaveChangesAsync();

var metadata = await theSession.MetadataForAsync(target1);

metadata.CorrelationId.ShouldBe(theSession.CorrelationId);
metadata.CausationId.ShouldBe(theSession.CausationId);
metadata.LastModifiedBy.ShouldBe(theSession.LastModifiedBy);
}
}

0 comments on commit 4901af9

Please sign in to comment.