diff --git a/BTCPayServer.Data/Data/WalletObjectData.cs b/BTCPayServer.Data/Data/WalletObjectData.cs index dbbb1ed4b..a9c48720a 100644 --- a/BTCPayServer.Data/Data/WalletObjectData.cs +++ b/BTCPayServer.Data/Data/WalletObjectData.cs @@ -27,36 +27,36 @@ namespace BTCPayServer.Data public string Id { get; set; } public string Data { get; set; } - public List ChildLinks { get; set; } - public List ParentLinks { get; set; } + public List Bs { get; set; } + public List As { get; set; } public IEnumerable<(string type, string id, string linkdata, string objectdata)> GetLinks() { - if (ChildLinks is not null) - foreach (var c in ChildLinks) + if (Bs is not null) + foreach (var c in Bs) { - yield return (c.ChildType, c.ChildId, c.Data, c.Child?.Data); + yield return (c.BType, c.BId, c.Data, c.B?.Data); } - if (ParentLinks is not null) - foreach (var c in ParentLinks) + if (As is not null) + foreach (var c in As) { - yield return (c.ParentType, c.ParentId, c.Data, c.Parent?.Data); + yield return (c.AType, c.AId, c.Data, c.A?.Data); } } public IEnumerable GetNeighbours() { - if (ChildLinks != null) - foreach (var c in ChildLinks) + if (Bs != null) + foreach (var c in Bs) { - if (c.Child != null) - yield return c.Child; + if (c.B != null) + yield return c.B; } - if (ParentLinks != null) - foreach (var c in ParentLinks) + if (As != null) + foreach (var c in As) { - if (c.Parent != null) - yield return c.Parent; + if (c.A != null) + yield return c.A; } } diff --git a/BTCPayServer.Data/Data/WalletObjectLinkData.cs b/BTCPayServer.Data/Data/WalletObjectLinkData.cs index 8c9359e65..9393c4589 100644 --- a/BTCPayServer.Data/Data/WalletObjectLinkData.cs +++ b/BTCPayServer.Data/Data/WalletObjectLinkData.cs @@ -11,14 +11,14 @@ namespace BTCPayServer.Data public class WalletObjectLinkData { public string WalletId { get; set; } - public string ParentType { get; set; } - public string ParentId { get; set; } - public string ChildType { get; set; } - public string ChildId { get; set; } + public string AType { get; set; } + public string AId { get; set; } + public string BType { get; set; } + public string BId { get; set; } public string Data { get; set; } - public WalletObjectData Parent { get; set; } - public WalletObjectData Child { get; set; } + public WalletObjectData A { get; set; } + public WalletObjectData B { get; set; } internal static void OnModelCreating(ModelBuilder builder, DatabaseFacade databaseFacade) { @@ -26,28 +26,28 @@ namespace BTCPayServer.Data new { o.WalletId, - o.ParentType, - o.ParentId, - o.ChildType, - o.ChildId, + o.AType, + o.AId, + o.BType, + o.BId, }); builder.Entity().HasIndex(o => new { o.WalletId, - o.ChildType, - o.ChildId, + o.BType, + o.BId, }); builder.Entity() - .HasOne(o => o.Parent) - .WithMany(o => o.ChildLinks) - .HasForeignKey(o => new { o.WalletId, o.ParentType, o.ParentId }) + .HasOne(o => o.A) + .WithMany(o => o.Bs) + .HasForeignKey(o => new { o.WalletId, o.AType, o.AId }) .OnDelete(DeleteBehavior.Cascade); builder.Entity() - .HasOne(o => o.Child) - .WithMany(o => o.ParentLinks) - .HasForeignKey(o => new { o.WalletId, o.ChildType, o.ChildId }) + .HasOne(o => o.B) + .WithMany(o => o.As) + .HasForeignKey(o => new { o.WalletId, o.BType, o.BId }) .OnDelete(DeleteBehavior.Cascade); if (databaseFacade.IsNpgsql()) diff --git a/BTCPayServer.Data/Migrations/20220929132704_label.cs b/BTCPayServer.Data/Migrations/20220929132704_label.cs index 7d67d16f2..0cb665e2f 100644 --- a/BTCPayServer.Data/Migrations/20220929132704_label.cs +++ b/BTCPayServer.Data/Migrations/20220929132704_label.cs @@ -40,33 +40,33 @@ namespace BTCPayServer.Migrations columns: table => new { WalletId = table.Column(type: "TEXT", nullable: false), - ParentType = table.Column(type: "TEXT", nullable: false), - ParentId = table.Column(type: "TEXT", nullable: false), - ChildType = table.Column(type: "TEXT", nullable: false), - ChildId = table.Column(type: "TEXT", nullable: false), + AType = table.Column(type: "TEXT", nullable: false), + AId = table.Column(type: "TEXT", nullable: false), + BType = table.Column(type: "TEXT", nullable: false), + BId = table.Column(type: "TEXT", nullable: false), Data = table.Column(type: migrationBuilder.IsNpgsql() ? "JSONB" : "TEXT", nullable: true) }, constraints: table => { - table.PrimaryKey("PK_WalletObjectLinks", x => new { x.WalletId, x.ParentType, x.ParentId, x.ChildType, x.ChildId }); + table.PrimaryKey("PK_WalletObjectLinks", x => new { x.WalletId, x.AType, x.AId, x.BType, x.BId }); table.ForeignKey( - name: "FK_WalletObjectLinks_WalletObjects_WalletId_ChildType_ChildId", - columns: x => new { x.WalletId, x.ChildType, x.ChildId }, + name: "FK_WalletObjectLinks_WalletObjects_WalletId_BType_BId", + columns: x => new { x.WalletId, x.BType, x.BId }, principalTable: "WalletObjects", principalColumns: new[] { "WalletId", "Type", "Id" }, onDelete: ReferentialAction.Cascade); table.ForeignKey( - name: "FK_WalletObjectLinks_WalletObjects_WalletId_ParentType_ParentId", - columns: x => new { x.WalletId, x.ParentType, x.ParentId }, + name: "FK_WalletObjectLinks_WalletObjects_WalletId_AType_AId", + columns: x => new { x.WalletId, x.AType, x.AId }, principalTable: "WalletObjects", principalColumns: new[] { "WalletId", "Type", "Id" }, onDelete: ReferentialAction.Cascade); }); migrationBuilder.CreateIndex( - name: "IX_WalletObjectLinks_WalletId_ChildType_ChildId", + name: "IX_WalletObjectLinks_WalletId_BType_BId", table: "WalletObjectLinks", - columns: new[] { "WalletId", "ChildType", "ChildId" }); + columns: new[] { "WalletId", "BType", "BId" }); } protected override void Down(MigrationBuilder migrationBuilder) diff --git a/BTCPayServer.Data/Migrations/ApplicationDbContextModelSnapshot.cs b/BTCPayServer.Data/Migrations/ApplicationDbContextModelSnapshot.cs index 79e3591e1..00ce9916c 100644 --- a/BTCPayServer.Data/Migrations/ApplicationDbContextModelSnapshot.cs +++ b/BTCPayServer.Data/Migrations/ApplicationDbContextModelSnapshot.cs @@ -872,24 +872,24 @@ namespace BTCPayServer.Migrations b.Property("WalletId") .HasColumnType("TEXT"); - b.Property("ParentType") + b.Property("AType") .HasColumnType("TEXT"); - b.Property("ParentId") + b.Property("AId") .HasColumnType("TEXT"); - b.Property("ChildType") + b.Property("BType") .HasColumnType("TEXT"); - b.Property("ChildId") + b.Property("BId") .HasColumnType("TEXT"); b.Property("Data") .HasColumnType("TEXT"); - b.HasKey("WalletId", "ParentType", "ParentId", "ChildType", "ChildId"); + b.HasKey("WalletId", "AType", "AId", "BType", "BId"); - b.HasIndex("WalletId", "ChildType", "ChildId"); + b.HasIndex("WalletId", "BType", "BId"); b.ToTable("WalletObjectLinks"); }); @@ -1384,21 +1384,21 @@ namespace BTCPayServer.Migrations modelBuilder.Entity("BTCPayServer.Data.WalletObjectLinkData", b => { - b.HasOne("BTCPayServer.Data.WalletObjectData", "Child") - .WithMany("ParentLinks") - .HasForeignKey("WalletId", "ChildType", "ChildId") + b.HasOne("BTCPayServer.Data.WalletObjectData", "A") + .WithMany("Bs") + .HasForeignKey("WalletId", "AType", "AId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); - b.HasOne("BTCPayServer.Data.WalletObjectData", "Parent") - .WithMany("ChildLinks") - .HasForeignKey("WalletId", "ParentType", "ParentId") + b.HasOne("BTCPayServer.Data.WalletObjectData", "B") + .WithMany("As") + .HasForeignKey("WalletId", "BType", "BId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); - b.Navigation("Child"); + b.Navigation("A"); - b.Navigation("Parent"); + b.Navigation("B"); }); modelBuilder.Entity("BTCPayServer.Data.WalletTransactionData", b => @@ -1545,9 +1545,9 @@ namespace BTCPayServer.Migrations modelBuilder.Entity("BTCPayServer.Data.WalletObjectData", b => { - b.Navigation("ChildLinks"); + b.Navigation("As"); - b.Navigation("ParentLinks"); + b.Navigation("Bs"); }); modelBuilder.Entity("BTCPayServer.Data.WebhookData", b => diff --git a/BTCPayServer/HostedServices/DbMigrationsHostedService.cs b/BTCPayServer/HostedServices/DbMigrationsHostedService.cs index 36cb1d149..30e742cb9 100644 --- a/BTCPayServer/HostedServices/DbMigrationsHostedService.cs +++ b/BTCPayServer/HostedServices/DbMigrationsHostedService.cs @@ -173,10 +173,10 @@ next: db.WalletObjectLinks.Add(new WalletObjectLinkData() { WalletId = tx.WalletDataId, - ChildType = Data.WalletObjectData.Types.Tx, - ChildId = tx.TransactionId, - ParentType = Data.WalletObjectData.Types.Label, - ParentId = labelId + BType = Data.WalletObjectData.Types.Tx, + BId = tx.TransactionId, + AType = Data.WalletObjectData.Types.Label, + AId = labelId }); if (label.Value is ReferenceLabel reflabel) @@ -195,10 +195,10 @@ next: db.WalletObjectLinks.Add(new WalletObjectLinkData() { WalletId = tx.WalletDataId, - ChildType = Data.WalletObjectData.Types.Tx, - ChildId = tx.TransactionId, - ParentType = reflabel.Type, - ParentId = reflabel.Reference ?? String.Empty + BType = Data.WalletObjectData.Types.Tx, + BId = tx.TransactionId, + AType = reflabel.Type, + AId = reflabel.Reference ?? String.Empty }); } } @@ -224,10 +224,10 @@ next: db.WalletObjectLinks.Add(new WalletObjectLinkData() { WalletId = tx.WalletDataId, - ChildType = Data.WalletObjectData.Types.Tx, - ChildId = tx.TransactionId, - ParentType = "payout", - ParentId = payout + BType = Data.WalletObjectData.Types.Tx, + BId = tx.TransactionId, + AType = "payout", + AId = payout }); } } diff --git a/BTCPayServer/Services/WalletRepository.cs b/BTCPayServer/Services/WalletRepository.cs index b71cdb943..94265278e 100644 --- a/BTCPayServer/Services/WalletRepository.cs +++ b/BTCPayServer/Services/WalletRepository.cs @@ -78,7 +78,7 @@ namespace BTCPayServer.Services using var ctx = _ContextFactory.CreateContext(); - // If we are using postgres, the `transactionIds.Contains(w.ChildId)` result in a long query like `ANY(@txId1, @txId2, @txId3, @txId4)` + // If we are using postgres, the `transactionIds.Contains(w.BId)` result in a long query like `ANY(@txId1, @txId2, @txId3, @txId4)` // Such request isn't well optimized by postgres, and create different requests clogging up // pg_stat_statements output, making it impossible to analyze the performance impact of this query. // On top of this, the entity version is doing 2 left join to satisfy the Include queries, resulting in n*m row returned for each transaction. @@ -106,9 +106,9 @@ namespace BTCPayServer.Services var query = $"SELECT wos.\"WalletId\", wos.\"Id\", wos.\"Type\", wos.\"Data\", wol.\"LinkData\", wol.\"Type2\", wol.\"Id2\"{includeNeighbourSelect} FROM ({selectWalletObjects}) wos " + $"LEFT JOIN LATERAL ( " + - "SELECT \"ParentType\" AS \"Type2\", \"ParentId\" AS \"Id2\", \"Data\" AS \"LinkData\" FROM \"WalletObjectLinks\" WHERE \"WalletId\"=wos.\"WalletId\" AND \"ChildType\"=wos.\"Type\" AND \"ChildId\"=wos.\"Id\" " + + "SELECT \"AType\" AS \"Type2\", \"AId\" AS \"Id2\", \"Data\" AS \"LinkData\" FROM \"WalletObjectLinks\" WHERE \"WalletId\"=wos.\"WalletId\" AND \"BType\"=wos.\"Type\" AND \"BId\"=wos.\"Id\" " + "UNION " + - "SELECT \"ChildType\" AS \"Type2\", \"ChildId\" AS \"Id2\", \"Data\" AS \"LinkData\" FROM \"WalletObjectLinks\" WHERE \"WalletId\"=wos.\"WalletId\" AND \"ParentType\"=wos.\"Type\" AND \"ParentId\"=wos.\"Id\"" + + "SELECT \"BType\" AS \"Type2\", \"BId\" AS \"Id2\", \"Data\" AS \"LinkData\" FROM \"WalletObjectLinks\" WHERE \"WalletId\"=wos.\"WalletId\" AND \"AType\"=wos.\"Type\" AND \"AId\"=wos.\"Id\"" + $" ) wol ON true " + includeNeighbourJoin; cmd.CommandText = query; if (queryObject.WalletId is not null) @@ -177,21 +177,21 @@ namespace BTCPayServer.Services else { wosById.Add(id, wo); - wo.ChildLinks = new List(); + wo.Bs = new List(); } if (reader["Type2"] is not DBNull) { var l = new WalletObjectLinkData() { - ChildType = (string)reader["Type2"], - ChildId = (string)reader["Id2"], + BType = (string)reader["Type2"], + BId = (string)reader["Id2"], Data = reader["LinkData"] is DBNull ? null : (string)reader["LinkData"] }; - wo.ChildLinks.Add(l); - l.Child = new WalletObjectData() + wo.Bs.Add(l); + l.B = new WalletObjectData() { - Type = l.ChildType, - Id = l.ChildId, + Type = l.BType, + Id = l.BId, Data = (!queryObject.IncludeNeighbours || reader["Data2"] is DBNull) ? null : (string)reader["Data2"] }; } @@ -215,8 +215,8 @@ namespace BTCPayServer.Services } if (queryObject.IncludeNeighbours) { - q = q.Include(o => o.ChildLinks).ThenInclude(o => o.Child) - .Include(o => o.ParentLinks).ThenInclude(o => o.Parent); + q = q.Include(o => o.Bs).ThenInclude(o => o.B) + .Include(o => o.As).ThenInclude(o => o.A); } q = q.AsNoTracking(); @@ -299,10 +299,10 @@ namespace BTCPayServer.Services var l = new WalletObjectLinkData() { WalletId = a.WalletId.ToString(), - ParentType = a.Type, - ParentId = a.Id, - ChildType = b.Type, - ChildId = b.Id, + AType = a.Type, + AId = a.Id, + BType = b.Type, + BId = b.Id, Data = data?.ToString(Formatting.None) }; ctx.WalletObjectLinks.Add(l); @@ -345,10 +345,10 @@ namespace BTCPayServer.Services var l = new WalletObjectLinkData() { WalletId = a.WalletId.ToString(), - ParentType = a.Type, - ParentId = a.Id, - ChildType = b.Type, - ChildId = b.Id, + AType = a.Type, + AId = a.Id, + BType = b.Type, + BId = b.Id, Data = data?.ToString(Formatting.None) }; var e = ctx.WalletObjectLinks.Add(l); @@ -453,10 +453,10 @@ namespace BTCPayServer.Services ctx.WalletObjectLinks.Remove(new WalletObjectLinkData() { WalletId = a.WalletId.ToString(), - ParentId = a.Id, - ParentType = a.Type, - ChildId = b.Id, - ChildType = b.Type + AId = a.Id, + AType = a.Type, + BId = b.Id, + BType = b.Type }); try {