From 9ae62d0259f70f91d260ce717049f6706d272957 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Pawelec?= Date: Wed, 18 Sep 2024 16:12:00 +0200 Subject: [PATCH 1/3] align kv store query with common pattern. Add total_count to kv store keys query. --- CHANGELOG.md | 5 +- .../CommonDbContext.cs | 6 + .../EntityMetadataProcessor.cs | 15 +- .../LedgerExtension/KeyValueStoreProcessor.cs | 90 ++++- .../PostgresLedgerExtenderService.cs | 2 +- ... 20241001130214_InitialCreate.Designer.cs} | 34 +- ...ate.cs => 20241001130214_InitialCreate.cs} | 24 ++ .../Migrations/IdempotentApplyMigrations.sql | 281 +++++++------- .../MigrationsDbContextModelSnapshot.cs | 32 ++ .../KeyValueStoreTotalsHistory.cs | 92 +++++ .../Queries/KeyValueStoreQueries.cs | 366 ++++++++++++++++++ .../Services/KeyValueStoreQuerier.cs | 209 ++-------- 12 files changed, 842 insertions(+), 314 deletions(-) rename src/RadixDlt.NetworkGateway.PostgresIntegration/Migrations/{20240927111052_InitialCreate.Designer.cs => 20241001130214_InitialCreate.Designer.cs} (98%) rename src/RadixDlt.NetworkGateway.PostgresIntegration/Migrations/{20240927111052_InitialCreate.cs => 20241001130214_InitialCreate.cs} (98%) create mode 100644 src/RadixDlt.NetworkGateway.PostgresIntegration/Models/KeyValueStore/KeyValueStoreTotalsHistory.cs create mode 100644 src/RadixDlt.NetworkGateway.PostgresIntegration/Queries/KeyValueStoreQueries.cs diff --git a/CHANGELOG.md b/CHANGELOG.md index c28307e20..349674ee3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,7 +28,7 @@ Release built: _not released yet_ > - `/state/entity/page/non-fungible-vaults/` (when using `non_fungible_include_nfids` opt-in) ### API Changes - +- Restored previously removed `total_count` property to `/state/key-value-store/keys` endpoint. ### Database changes - Refactored multiple aggregates. Queries follow a similar strategy as key value stores and utilize `_entry_definition`, `_entry_history`, and `_totals_history` tables to return data @@ -50,7 +50,8 @@ Release built: _not released yet_ - New `non_fungible_vault_entry_definition` table, which holds information about non fungible held by a given vault. - New `non_fungible_vault_entry_history` table which holds history of given non fungible inside vault. - Renamed `entity_vault_history` to `vault_balance_history`. Holds information about vault content (amount of fungibles or count of non fungible ids inside vault) at a given state version. - + - Key value store + - New `key_value_store_totals_history` table, which holds total count of all keys under a given store at a given state version. ## 1.7.3 Release built: 26.09.2024 diff --git a/src/RadixDlt.NetworkGateway.PostgresIntegration/CommonDbContext.cs b/src/RadixDlt.NetworkGateway.PostgresIntegration/CommonDbContext.cs index 3829eb0c5..bb5551abc 100644 --- a/src/RadixDlt.NetworkGateway.PostgresIntegration/CommonDbContext.cs +++ b/src/RadixDlt.NetworkGateway.PostgresIntegration/CommonDbContext.cs @@ -154,6 +154,8 @@ internal abstract class CommonDbContext : DbContext public DbSet KeyValueStoreEntryHistory => Set(); + public DbSet KeyValueStoreTotalsHistory => Set(); + public DbSet ValidatorCumulativeEmissionHistory => Set(); public DbSet NonFungibleSchemaHistory => Set(); @@ -403,6 +405,10 @@ private static void HookupDefinitions(ModelBuilder modelBuilder) .Entity() .HasIndex(e => new { e.KeyValueStoreEntityId, e.Key }); + modelBuilder + .Entity() + .HasIndex(e => new { e.EntityId, e.FromStateVersion }); + modelBuilder .Entity() .HasIndex(e => new { e.NonFungibleResourceEntityId, e.FromStateVersion }); diff --git a/src/RadixDlt.NetworkGateway.PostgresIntegration/LedgerExtension/EntityMetadataProcessor.cs b/src/RadixDlt.NetworkGateway.PostgresIntegration/LedgerExtension/EntityMetadataProcessor.cs index 61660eefc..2f8b0aabd 100644 --- a/src/RadixDlt.NetworkGateway.PostgresIntegration/LedgerExtension/EntityMetadataProcessor.cs +++ b/src/RadixDlt.NetworkGateway.PostgresIntegration/LedgerExtension/EntityMetadataProcessor.cs @@ -77,7 +77,7 @@ internal record struct MetadataEntryDbLookup(long EntityId, string Key); internal record struct MetadataChangePointerLookup(long EntityId, long StateVersion); -internal record struct MetadataEntry(CoreModel.MetadataModuleEntrySubstate NewValue, CoreModel.MetadataModuleEntrySubstate? PreviousValue); +internal record struct MetadataEntry(CoreModel.MetadataModuleEntrySubstate NewSubstate, CoreModel.MetadataModuleEntrySubstate? PreviousSubstate); internal record MetadataChangePointer { @@ -95,7 +95,6 @@ internal class EntityMetadataProcessor private readonly Dictionary _entryDefinitionsToAdd = new(); private readonly List _entryHistoryToAdd = new(); private readonly List _totalsHistoryToAdd = new(); - private readonly Dictionary _mostRecentHistoryEntry = new(); private readonly ChangeTracker _changes = new(); @@ -157,8 +156,8 @@ public void ProcessChanges() foreach (var entry in change.Value.Entries) { - var isDeleted = entry.NewValue.Value == null; - var newEntry = entry.NewValue; + var isDeleted = entry.NewSubstate.Value == null; + var newEntry = entry.NewSubstate; _entryHistoryToAdd.Add( new EntityMetadataEntryHistory @@ -173,17 +172,17 @@ public void ProcessChanges() switch (entry) { - case { PreviousValue: null, NewValue.Value: null }: + case { PreviousSubstate: null, NewSubstate.Value: null }: newTotals.TotalEntriesIncludingDeleted++; break; - case { PreviousValue: null, NewValue.Value: not null }: + case { PreviousSubstate: null, NewSubstate.Value: not null }: newTotals.TotalEntriesIncludingDeleted++; newTotals.TotalEntriesExcludingDeleted++; break; - case { PreviousValue.Value: not null, NewValue.Value: null }: + case { PreviousSubstate.Value: not null, NewSubstate.Value: null }: newTotals.TotalEntriesExcludingDeleted--; break; - case { PreviousValue.Value: null, NewValue.Value: not null }: + case { PreviousSubstate.Value: null, NewSubstate.Value: not null }: newTotals.TotalEntriesExcludingDeleted++; break; } diff --git a/src/RadixDlt.NetworkGateway.PostgresIntegration/LedgerExtension/KeyValueStoreProcessor.cs b/src/RadixDlt.NetworkGateway.PostgresIntegration/LedgerExtension/KeyValueStoreProcessor.cs index ddcf4f1eb..b4fdec0eb 100644 --- a/src/RadixDlt.NetworkGateway.PostgresIntegration/LedgerExtension/KeyValueStoreProcessor.cs +++ b/src/RadixDlt.NetworkGateway.PostgresIntegration/LedgerExtension/KeyValueStoreProcessor.cs @@ -77,7 +77,7 @@ internal record struct KeyValueStoreEntryDbLookup(long KeyValueStoreEntityId, Va internal record struct KeyValueStoreChangePointerLookup(long KeyValueStoreEntityId, long StateVersion, ValueBytes Key); -internal record KeyValueStoreChangePointer(CoreModel.GenericKeyValueStoreEntrySubstate KeyValueStoreEntry); +internal record KeyValueStoreChangePointer(CoreModel.GenericKeyValueStoreEntrySubstate NewSubstate, CoreModel.GenericKeyValueStoreEntrySubstate? PreviousSubstate); internal class KeyValueStoreProcessor { @@ -85,9 +85,11 @@ internal class KeyValueStoreProcessor private readonly Dictionary _observedEntryDefinitions = new(); private readonly Dictionary _existingEntryDefinitions = new(); + private readonly Dictionary _existingTotalsHistory = new(); private readonly List _entryDefinitionsToAdd = new(); private readonly List _entryHistoryToAdd = new(); + private readonly List _totalsHistoryToAdd = new(); private ChangeTracker _changes = new(); @@ -96,14 +98,16 @@ public KeyValueStoreProcessor(ProcessorContext context) _context = context; } - public void VisitUpsert(CoreModel.Substate substateData, ReferencedEntity referencedEntity, long stateVersion) + public void VisitUpsert(CoreModel.IUpsertedSubstate substate, ReferencedEntity referencedEntity, long stateVersion) { + var substateData = substate.Value.SubstateData; + if (substateData is CoreModel.GenericKeyValueStoreEntrySubstate genericKeyValueStoreEntry) { var key = (ValueBytes)genericKeyValueStoreEntry.Key.KeyData.GetDataBytes(); var kvStoreEntryLookup = new KeyValueStoreChangePointerLookup(referencedEntity.DatabaseId, stateVersion, key); - _changes.Add(kvStoreEntryLookup, new KeyValueStoreChangePointer(genericKeyValueStoreEntry)); + _changes.Add(kvStoreEntryLookup, new KeyValueStoreChangePointer(genericKeyValueStoreEntry, substate.PreviousValue?.SubstateData as CoreModel.GenericKeyValueStoreEntrySubstate)); _observedEntryDefinitions.TryAdd(new KeyValueStoreEntryDbLookup(referencedEntity.DatabaseId, key), stateVersion); } } @@ -111,6 +115,7 @@ public void VisitUpsert(CoreModel.Substate substateData, ReferencedEntity refere public async Task LoadDependencies() { _existingEntryDefinitions.AddRange(await ExistingKeyValueStoreEntryDefinitions()); + _existingTotalsHistory.AddRange(await ExistingKeyValueStoreTotalsHistory()); } public void ProcessChanges() @@ -131,17 +136,48 @@ public void ProcessChanges() foreach (var change in _changes.AsEnumerable()) { - var isDeleted = change.Value.KeyValueStoreEntry.Value == null; + var isDeleted = change.Value.NewSubstate.Value == null; _entryHistoryToAdd.Add(new KeyValueStoreEntryHistory { Id = _context.Sequences.KeyValueStoreEntryHistorySequence++, FromStateVersion = change.Key.StateVersion, KeyValueStoreEntryDefinitionId = _existingEntryDefinitions[new KeyValueStoreEntryDbLookup(change.Key.KeyValueStoreEntityId, change.Key.Key)].Id, - Value = isDeleted ? null : change.Value.KeyValueStoreEntry.Value!.Data.StructData.GetDataBytes(), + Value = isDeleted ? null : change.Value.NewSubstate.Value!.Data.StructData.GetDataBytes(), IsDeleted = isDeleted, - IsLocked = change.Value.KeyValueStoreEntry.IsLocked, + IsLocked = change.Value.NewSubstate.IsLocked, }); + + var totalsExists = _existingTotalsHistory.TryGetValue(change.Key.KeyValueStoreEntityId, out var previousTotals); + + var newTotals = new KeyValueStoreTotalsHistory + { + Id = _context.Sequences.EntityMetadataTotalsHistorySequence++, + FromStateVersion = change.Key.StateVersion, + EntityId = change.Key.KeyValueStoreEntityId, + TotalEntriesExcludingDeleted = totalsExists ? previousTotals!.TotalEntriesExcludingDeleted : 0, + TotalEntriesIncludingDeleted = totalsExists ? previousTotals!.TotalEntriesIncludingDeleted : 0, + }; + + switch (change.Value) + { + case { PreviousSubstate: null, NewSubstate.Value: null }: + newTotals.TotalEntriesIncludingDeleted++; + break; + case { PreviousSubstate: null, NewSubstate.Value: not null }: + newTotals.TotalEntriesIncludingDeleted++; + newTotals.TotalEntriesExcludingDeleted++; + break; + case { PreviousSubstate.Value: not null, NewSubstate.Value: null }: + newTotals.TotalEntriesExcludingDeleted--; + break; + case { PreviousSubstate.Value: null, NewSubstate.Value: not null }: + newTotals.TotalEntriesExcludingDeleted++; + break; + } + + _existingTotalsHistory[change.Key.KeyValueStoreEntityId] = newTotals; + _totalsHistoryToAdd.Add(newTotals); } } @@ -151,6 +187,7 @@ public async Task SaveEntities() rowsInserted += await CopyKeyValueStoreEntryDefinition(); rowsInserted += await CopyKeyValueStoreEntryHistory(); + rowsInserted += await CopyKeyValueStoreTotalsHistory(); return rowsInserted; } @@ -173,6 +210,35 @@ FROM key_value_store_entry_definition e => new KeyValueStoreEntryDbLookup(e.KeyValueStoreEntityId, (ValueBytes)e.Key)); } + private async Task> ExistingKeyValueStoreTotalsHistory() + { + var entityIds = _observedEntryDefinitions + .Keys + .Select(x => x.KeyValueStoreEntityId) + .ToHashSet(); + + if (entityIds.Count == 0) + { + return ImmutableDictionary.Empty; + } + + return await _context.ReadHelper.LoadDependencies( + @$" +WITH variables (entity_id) AS ( + SELECT UNNEST({entityIds}) +) +SELECT kvsth.* +FROM variables +INNER JOIN LATERAL ( + SELECT * + FROM key_value_store_totals_history + WHERE entity_id = variables.entity_id + ORDER BY from_state_version DESC + LIMIT 1 +) kvsth ON true;", + e => e.EntityId); + } + private Task CopyKeyValueStoreEntryDefinition() => _context.WriteHelper.Copy( _entryDefinitionsToAdd, "COPY key_value_store_entry_definition (id, from_state_version, key_value_store_entity_id, key) FROM STDIN (FORMAT BINARY)", @@ -196,4 +262,16 @@ private Task CopyKeyValueStoreEntryHistory() => _context.WriteHelper.Copy( await writer.WriteAsync(e.IsDeleted, NpgsqlDbType.Boolean, token); await writer.WriteAsync(e.IsLocked, NpgsqlDbType.Boolean, token); }); + + private Task CopyKeyValueStoreTotalsHistory() => _context.WriteHelper.Copy( + _totalsHistoryToAdd, + "COPY key_value_store_totals_history (id, from_state_version, entity_id, total_entries_including_deleted, total_entries_excluding_deleted) FROM STDIN (FORMAT BINARY)", + async (writer, e, token) => + { + await writer.WriteAsync(e.Id, NpgsqlDbType.Bigint, token); + await writer.WriteAsync(e.FromStateVersion, NpgsqlDbType.Bigint, token); + await writer.WriteAsync(e.EntityId, NpgsqlDbType.Bigint, token); + await writer.WriteAsync(e.TotalEntriesIncludingDeleted, NpgsqlDbType.Bigint, token); + await writer.WriteAsync(e.TotalEntriesExcludingDeleted, NpgsqlDbType.Bigint, token); + }); } diff --git a/src/RadixDlt.NetworkGateway.PostgresIntegration/LedgerExtension/PostgresLedgerExtenderService.cs b/src/RadixDlt.NetworkGateway.PostgresIntegration/LedgerExtension/PostgresLedgerExtenderService.cs index 845f16db8..b871d16d0 100644 --- a/src/RadixDlt.NetworkGateway.PostgresIntegration/LedgerExtension/PostgresLedgerExtenderService.cs +++ b/src/RadixDlt.NetworkGateway.PostgresIntegration/LedgerExtension/PostgresLedgerExtenderService.cs @@ -842,7 +842,7 @@ private async Task ProcessTransactions(ReadWriteDbContext db accountResourcePreferenceRulesProcessor.VisitUpsert(substateData, referencedEntity, stateVersion); accountDefaultDepositRuleProcessor.VisitUpsert(substateData, referencedEntity, stateVersion); accountAuthorizedDepositorsProcessor.VisitUpsert(substateData, referencedEntity, stateVersion); - keyValueStoreProcessor.VisitUpsert(substateData, referencedEntity, stateVersion); + keyValueStoreProcessor.VisitUpsert(substate, referencedEntity, stateVersion); validatorProcessor.VisitUpsert(substateData, referencedEntity, stateVersion, passingEpoch); accountLockerProcessor.VisitUpsert(substateData, referencedEntity, stateVersion); affectedGlobalEntitiesProcessor.VisitUpsert(referencedEntity, stateVersion); diff --git a/src/RadixDlt.NetworkGateway.PostgresIntegration/Migrations/20240927111052_InitialCreate.Designer.cs b/src/RadixDlt.NetworkGateway.PostgresIntegration/Migrations/20241001130214_InitialCreate.Designer.cs similarity index 98% rename from src/RadixDlt.NetworkGateway.PostgresIntegration/Migrations/20240927111052_InitialCreate.Designer.cs rename to src/RadixDlt.NetworkGateway.PostgresIntegration/Migrations/20241001130214_InitialCreate.Designer.cs index fbbf27911..4ec14acff 100644 --- a/src/RadixDlt.NetworkGateway.PostgresIntegration/Migrations/20240927111052_InitialCreate.Designer.cs +++ b/src/RadixDlt.NetworkGateway.PostgresIntegration/Migrations/20241001130214_InitialCreate.Designer.cs @@ -81,7 +81,7 @@ namespace RadixDlt.NetworkGateway.PostgresIntegration.Migrations { [DbContext(typeof(MigrationsDbContext))] - [Migration("20240927111052_InitialCreate")] + [Migration("20241001130214_InitialCreate")] partial class InitialCreate { /// @@ -995,6 +995,38 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.ToTable("key_value_store_schema_history"); }); + modelBuilder.Entity("RadixDlt.NetworkGateway.PostgresIntegration.Models.KeyValueStoreTotalsHistory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("EntityId") + .HasColumnType("bigint") + .HasColumnName("entity_id"); + + b.Property("FromStateVersion") + .HasColumnType("bigint") + .HasColumnName("from_state_version"); + + b.Property("TotalEntriesExcludingDeleted") + .HasColumnType("bigint") + .HasColumnName("total_entries_excluding_deleted"); + + b.Property("TotalEntriesIncludingDeleted") + .HasColumnType("bigint") + .HasColumnName("total_entries_including_deleted"); + + b.HasKey("Id"); + + b.HasIndex("EntityId", "FromStateVersion"); + + b.ToTable("key_value_store_totals_history"); + }); + modelBuilder.Entity("RadixDlt.NetworkGateway.PostgresIntegration.Models.LedgerTransaction", b => { b.Property("StateVersion") diff --git a/src/RadixDlt.NetworkGateway.PostgresIntegration/Migrations/20240927111052_InitialCreate.cs b/src/RadixDlt.NetworkGateway.PostgresIntegration/Migrations/20241001130214_InitialCreate.cs similarity index 98% rename from src/RadixDlt.NetworkGateway.PostgresIntegration/Migrations/20240927111052_InitialCreate.cs rename to src/RadixDlt.NetworkGateway.PostgresIntegration/Migrations/20241001130214_InitialCreate.cs index de9905e83..e468d4452 100644 --- a/src/RadixDlt.NetworkGateway.PostgresIntegration/Migrations/20240927111052_InitialCreate.cs +++ b/src/RadixDlt.NetworkGateway.PostgresIntegration/Migrations/20241001130214_InitialCreate.cs @@ -523,6 +523,22 @@ protected override void Up(MigrationBuilder migrationBuilder) table.PrimaryKey("PK_key_value_store_schema_history", x => x.id); }); + migrationBuilder.CreateTable( + name: "key_value_store_totals_history", + columns: table => new + { + id = table.Column(type: "bigint", nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + from_state_version = table.Column(type: "bigint", nullable: false), + entity_id = table.Column(type: "bigint", nullable: false), + total_entries_including_deleted = table.Column(type: "bigint", nullable: false), + total_entries_excluding_deleted = table.Column(type: "bigint", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_key_value_store_totals_history", x => x.id); + }); + migrationBuilder.CreateTable( name: "ledger_transaction_markers", columns: table => new @@ -1172,6 +1188,11 @@ protected override void Up(MigrationBuilder migrationBuilder) table: "key_value_store_schema_history", columns: new[] { "key_value_store_entity_id", "from_state_version" }); + migrationBuilder.CreateIndex( + name: "IX_key_value_store_totals_history_entity_id_from_state_version", + table: "key_value_store_totals_history", + columns: new[] { "entity_id", "from_state_version" }); + migrationBuilder.CreateIndex( name: "IX_ledger_transaction_markers_entity_id_state_version", table: "ledger_transaction_markers", @@ -1486,6 +1507,9 @@ protected override void Down(MigrationBuilder migrationBuilder) migrationBuilder.DropTable( name: "key_value_store_schema_history"); + migrationBuilder.DropTable( + name: "key_value_store_totals_history"); + migrationBuilder.DropTable( name: "ledger_transaction_markers"); diff --git a/src/RadixDlt.NetworkGateway.PostgresIntegration/Migrations/IdempotentApplyMigrations.sql b/src/RadixDlt.NetworkGateway.PostgresIntegration/Migrations/IdempotentApplyMigrations.sql index ead97d99e..b1905128b 100644 --- a/src/RadixDlt.NetworkGateway.PostgresIntegration/Migrations/IdempotentApplyMigrations.sql +++ b/src/RadixDlt.NetworkGateway.PostgresIntegration/Migrations/IdempotentApplyMigrations.sql @@ -9,7 +9,7 @@ START TRANSACTION; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE TYPE account_default_deposit_rule AS ENUM ('accept', 'reject', 'allow_existing'); CREATE TYPE account_resource_preference_rule AS ENUM ('allowed', 'disallowed'); CREATE TYPE authorized_depositor_badge_type AS ENUM ('resource', 'non_fungible'); @@ -37,7 +37,7 @@ END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE TABLE account_authorized_depositor_aggregate_history ( id bigint GENERATED BY DEFAULT AS IDENTITY, from_state_version bigint NOT NULL, @@ -50,7 +50,7 @@ END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE TABLE account_authorized_depositor_entry_history ( id bigint GENERATED BY DEFAULT AS IDENTITY, from_state_version bigint NOT NULL, @@ -66,7 +66,7 @@ END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE TABLE account_default_deposit_rule_history ( id bigint GENERATED BY DEFAULT AS IDENTITY, from_state_version bigint NOT NULL, @@ -79,7 +79,7 @@ END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE TABLE account_locker_entry_definition ( id bigint GENERATED BY DEFAULT AS IDENTITY, from_state_version bigint NOT NULL, @@ -93,7 +93,7 @@ END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE TABLE account_locker_entry_resource_vault_definition ( id bigint GENERATED BY DEFAULT AS IDENTITY, from_state_version bigint NOT NULL, @@ -107,7 +107,7 @@ END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE TABLE account_locker_entry_touch_history ( id bigint GENERATED BY DEFAULT AS IDENTITY, from_state_version bigint NOT NULL, @@ -119,7 +119,7 @@ END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE TABLE account_resource_preference_rule_aggregate_history ( id bigint GENERATED BY DEFAULT AS IDENTITY, from_state_version bigint NOT NULL, @@ -132,7 +132,7 @@ END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE TABLE account_resource_preference_rule_entry_history ( id bigint GENERATED BY DEFAULT AS IDENTITY, from_state_version bigint NOT NULL, @@ -147,7 +147,7 @@ END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE TABLE component_method_royalty_aggregate_history ( id bigint GENERATED BY DEFAULT AS IDENTITY, from_state_version bigint NOT NULL, @@ -160,7 +160,7 @@ END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE TABLE component_method_royalty_entry_history ( id bigint GENERATED BY DEFAULT AS IDENTITY, from_state_version bigint NOT NULL, @@ -175,7 +175,7 @@ END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE TABLE entities ( id bigint GENERATED BY DEFAULT AS IDENTITY, from_state_version bigint NOT NULL, @@ -201,7 +201,7 @@ END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE TABLE entity_metadata_entry_definition ( id bigint GENERATED BY DEFAULT AS IDENTITY, from_state_version bigint NOT NULL, @@ -214,7 +214,7 @@ END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE TABLE entity_metadata_entry_history ( id bigint GENERATED BY DEFAULT AS IDENTITY, from_state_version bigint NOT NULL, @@ -229,7 +229,7 @@ END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE TABLE entity_metadata_totals_history ( id bigint GENERATED BY DEFAULT AS IDENTITY, from_state_version bigint NOT NULL, @@ -243,7 +243,7 @@ END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE TABLE entity_resource_balance_history ( id bigint GENERATED BY DEFAULT AS IDENTITY, from_state_version bigint NOT NULL, @@ -257,7 +257,7 @@ END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE TABLE entity_resource_entry_definition ( id bigint GENERATED BY DEFAULT AS IDENTITY, from_state_version bigint NOT NULL, @@ -271,7 +271,7 @@ END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE TABLE entity_resource_totals_history ( id bigint GENERATED BY DEFAULT AS IDENTITY, from_state_version bigint NOT NULL, @@ -286,7 +286,7 @@ END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE TABLE entity_resource_vault_entry_definition ( id bigint GENERATED BY DEFAULT AS IDENTITY, from_state_version bigint NOT NULL, @@ -300,7 +300,7 @@ END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE TABLE entity_resource_vault_totals_history ( id bigint GENERATED BY DEFAULT AS IDENTITY, from_state_version bigint NOT NULL, @@ -314,7 +314,7 @@ END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE TABLE entity_role_assignments_aggregate_history ( id bigint GENERATED BY DEFAULT AS IDENTITY, from_state_version bigint NOT NULL, @@ -328,7 +328,7 @@ END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE TABLE entity_role_assignments_entry_history ( id bigint GENERATED BY DEFAULT AS IDENTITY, from_state_version bigint NOT NULL, @@ -344,7 +344,7 @@ END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE TABLE entity_role_assignments_owner_role_history ( id bigint GENERATED BY DEFAULT AS IDENTITY, from_state_version bigint NOT NULL, @@ -357,7 +357,7 @@ END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE TABLE key_value_store_entry_definition ( id bigint GENERATED BY DEFAULT AS IDENTITY, from_state_version bigint NOT NULL, @@ -370,7 +370,7 @@ END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE TABLE key_value_store_entry_history ( id bigint GENERATED BY DEFAULT AS IDENTITY, from_state_version bigint NOT NULL, @@ -385,7 +385,7 @@ END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE TABLE key_value_store_schema_history ( id bigint GENERATED BY DEFAULT AS IDENTITY, from_state_version bigint NOT NULL, @@ -405,7 +405,21 @@ END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN + CREATE TABLE key_value_store_totals_history ( + id bigint GENERATED BY DEFAULT AS IDENTITY, + from_state_version bigint NOT NULL, + entity_id bigint NOT NULL, + total_entries_including_deleted bigint NOT NULL, + total_entries_excluding_deleted bigint NOT NULL, + CONSTRAINT "PK_key_value_store_totals_history" PRIMARY KEY (id) + ); + END IF; +END $EF$; + +DO $EF$ +BEGIN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE TABLE ledger_transaction_markers ( id bigint GENERATED BY DEFAULT AS IDENTITY, state_version bigint NOT NULL, @@ -425,7 +439,7 @@ END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE TABLE ledger_transactions ( state_version bigint NOT NULL, epoch bigint NOT NULL, @@ -473,7 +487,7 @@ END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE TABLE non_fungible_id_data_history ( id bigint GENERATED BY DEFAULT AS IDENTITY, from_state_version bigint NOT NULL, @@ -488,7 +502,7 @@ END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE TABLE non_fungible_id_definition ( id bigint GENERATED BY DEFAULT AS IDENTITY, from_state_version bigint NOT NULL, @@ -501,7 +515,7 @@ END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE TABLE non_fungible_id_location_history ( id bigint GENERATED BY DEFAULT AS IDENTITY, from_state_version bigint NOT NULL, @@ -514,7 +528,7 @@ END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE TABLE non_fungible_schema_history ( id bigint GENERATED BY DEFAULT AS IDENTITY, from_state_version bigint NOT NULL, @@ -530,7 +544,7 @@ END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE TABLE non_fungible_vault_entry_definition ( id bigint GENERATED BY DEFAULT AS IDENTITY, from_state_version bigint NOT NULL, @@ -543,7 +557,7 @@ END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE TABLE non_fungible_vault_entry_history ( id bigint GENERATED BY DEFAULT AS IDENTITY, from_state_version bigint NOT NULL, @@ -556,7 +570,7 @@ END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE TABLE package_blueprint_aggregate_history ( id bigint GENERATED BY DEFAULT AS IDENTITY, from_state_version bigint NOT NULL, @@ -569,7 +583,7 @@ END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE TABLE package_blueprint_history ( id bigint GENERATED BY DEFAULT AS IDENTITY, from_state_version bigint NOT NULL, @@ -589,7 +603,7 @@ END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE TABLE package_code_aggregate_history ( id bigint GENERATED BY DEFAULT AS IDENTITY, from_state_version bigint NOT NULL, @@ -602,7 +616,7 @@ END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE TABLE package_code_history ( id bigint GENERATED BY DEFAULT AS IDENTITY, from_state_version bigint NOT NULL, @@ -618,7 +632,7 @@ END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE TABLE pending_transactions ( id bigint GENERATED BY DEFAULT AS IDENTITY, payload_hash text NOT NULL, @@ -646,7 +660,7 @@ END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE TABLE resource_entity_supply_history ( id bigint GENERATED BY DEFAULT AS IDENTITY, from_state_version bigint NOT NULL, @@ -661,7 +675,7 @@ END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE TABLE resource_holders ( id bigint GENERATED BY DEFAULT AS IDENTITY, entity_id bigint NOT NULL, @@ -675,7 +689,7 @@ END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE TABLE schema_entry_aggregate_history ( id bigint GENERATED BY DEFAULT AS IDENTITY, from_state_version bigint NOT NULL, @@ -688,7 +702,7 @@ END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE TABLE schema_entry_definition ( id bigint GENERATED BY DEFAULT AS IDENTITY, from_state_version bigint NOT NULL, @@ -702,7 +716,7 @@ END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE TABLE state_history ( id bigint GENERATED BY DEFAULT AS IDENTITY, from_state_version bigint NOT NULL, @@ -721,7 +735,7 @@ END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE TABLE unverified_standard_metadata_aggregate_history ( id bigint GENERATED BY DEFAULT AS IDENTITY, from_state_version bigint NOT NULL, @@ -734,7 +748,7 @@ END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE TABLE unverified_standard_metadata_entry_history ( id bigint GENERATED BY DEFAULT AS IDENTITY, from_state_version bigint NOT NULL, @@ -751,7 +765,7 @@ END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE TABLE validator_cumulative_emission_history ( id bigint GENERATED BY DEFAULT AS IDENTITY, from_state_version bigint NOT NULL, @@ -767,7 +781,7 @@ END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE TABLE validator_public_key_history ( id bigint GENERATED BY DEFAULT AS IDENTITY, from_state_version bigint NOT NULL, @@ -781,7 +795,7 @@ END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE TABLE vault_balance_history ( id bigint GENERATED BY DEFAULT AS IDENTITY, from_state_version bigint NOT NULL, @@ -794,7 +808,7 @@ END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE TABLE pending_transaction_payloads ( id bigint GENERATED BY DEFAULT AS IDENTITY, pending_transaction_id bigint, @@ -807,7 +821,7 @@ END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE TABLE validator_active_set_history ( id bigint GENERATED BY DEFAULT AS IDENTITY, from_state_version bigint NOT NULL, @@ -822,548 +836,555 @@ END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE INDEX "IX_account_authorized_depositor_aggregate_history_account_enti~" ON account_authorized_depositor_aggregate_history (account_entity_id, from_state_version); END IF; END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE INDEX "IX_account_authorized_depositor_entry_history_account_entity_~1" ON account_authorized_depositor_entry_history (account_entity_id, resource_entity_id, non_fungible_id, from_state_version) WHERE discriminator = 'non_fungible'; END IF; END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE INDEX "IX_account_authorized_depositor_entry_history_account_entity_~2" ON account_authorized_depositor_entry_history (account_entity_id, resource_entity_id, from_state_version) WHERE discriminator = 'resource'; END IF; END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE INDEX "IX_account_authorized_depositor_entry_history_account_entity_i~" ON account_authorized_depositor_entry_history (account_entity_id, from_state_version); END IF; END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE INDEX "IX_account_default_deposit_rule_history_account_entity_id_from~" ON account_default_deposit_rule_history (account_entity_id, from_state_version); END IF; END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE UNIQUE INDEX "IX_account_locker_entry_definition_account_locker_entity_id_ac~" ON account_locker_entry_definition (account_locker_entity_id, account_entity_id); END IF; END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE INDEX "IX_account_locker_entry_resource_vault_definition_account_lock~" ON account_locker_entry_resource_vault_definition (account_locker_definition_id, from_state_version); END IF; END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE INDEX "IX_account_locker_entry_touch_history_account_locker_definitio~" ON account_locker_entry_touch_history (account_locker_definition_id, from_state_version); END IF; END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE INDEX "IX_account_resource_preference_rule_aggregate_history_account_~" ON account_resource_preference_rule_aggregate_history (account_entity_id, from_state_version); END IF; END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE INDEX "IX_account_resource_preference_rule_entry_history_account_enti~" ON account_resource_preference_rule_entry_history (account_entity_id, resource_entity_id, from_state_version); END IF; END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE INDEX "IX_component_method_royalty_aggregate_history_entity_id_from_s~" ON component_method_royalty_aggregate_history (entity_id, from_state_version); END IF; END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE INDEX "IX_component_method_royalty_entry_history_entity_id_from_state~" ON component_method_royalty_entry_history (entity_id, from_state_version); END IF; END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE INDEX "IX_component_method_royalty_entry_history_entity_id_method_nam~" ON component_method_royalty_entry_history (entity_id, method_name, from_state_version); END IF; END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE UNIQUE INDEX "IX_entities_address" ON entities (address); END IF; END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE INDEX "IX_entities_from_state_version" ON entities (from_state_version) WHERE discriminator = 'global_validator'; END IF; END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE INDEX "IX_entity_metadata_entry_definition_entity_id_from_state_versi~" ON entity_metadata_entry_definition (entity_id, from_state_version); END IF; END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE INDEX "IX_entity_metadata_entry_definition_entity_id_key" ON entity_metadata_entry_definition (entity_id, key); END IF; END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE INDEX "IX_entity_metadata_entry_history_entity_metadata_entry_definit~" ON entity_metadata_entry_history (entity_metadata_entry_definition_id, from_state_version); END IF; END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE INDEX "IX_entity_metadata_totals_history_entity_id_from_state_version" ON entity_metadata_totals_history (entity_id, from_state_version); END IF; END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE INDEX "IX_entity_resource_balance_history_entity_id_resource_entity_i~" ON entity_resource_balance_history (entity_id, resource_entity_id, from_state_version); END IF; END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE INDEX "IX_entity_resource_entry_definition_entity_id_from_state_versi~" ON entity_resource_entry_definition (entity_id, from_state_version); END IF; END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE INDEX "IX_entity_resource_entry_definition_fungibles" ON entity_resource_entry_definition (entity_id, from_state_version) WHERE resource_type = 'fungible'; END IF; END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE INDEX "IX_entity_resource_entry_definition_non_fungibles" ON entity_resource_entry_definition (entity_id, from_state_version) WHERE resource_type = 'non_fungible'; END IF; END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE INDEX "IX_entity_resource_totals_history_entity_id_from_state_version" ON entity_resource_totals_history (entity_id, from_state_version); END IF; END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE INDEX "IX_entity_resource_vault_entry_definition_entity_id_resource_e~" ON entity_resource_vault_entry_definition (entity_id, resource_entity_id, from_state_version); END IF; END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE INDEX "IX_entity_resource_vault_totals_history_entity_id_resource_ent~" ON entity_resource_vault_totals_history (entity_id, resource_entity_id, from_state_version); END IF; END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE INDEX "IX_entity_role_assignments_aggregate_history_entity_id_from_st~" ON entity_role_assignments_aggregate_history (entity_id, from_state_version); END IF; END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE INDEX "IX_entity_role_assignments_entry_history_entity_id_key_role_ke~" ON entity_role_assignments_entry_history (entity_id, key_role, key_module, from_state_version); END IF; END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE INDEX "IX_entity_role_assignments_owner_role_history_entity_id_from_s~" ON entity_role_assignments_owner_role_history (entity_id, from_state_version); END IF; END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE INDEX "IX_key_value_store_entry_definition_key_value_store_entity_id_~" ON key_value_store_entry_definition (key_value_store_entity_id, from_state_version); END IF; END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE INDEX "IX_key_value_store_entry_definition_key_value_store_entity_id~1" ON key_value_store_entry_definition (key_value_store_entity_id, key); END IF; END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE INDEX "IX_key_value_store_entry_history_key_value_store_entry_definit~" ON key_value_store_entry_history (key_value_store_entry_definition_id, from_state_version); END IF; END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE INDEX "IX_key_value_store_schema_history_key_value_store_entity_id_fr~" ON key_value_store_schema_history (key_value_store_entity_id, from_state_version); END IF; END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN + CREATE INDEX "IX_key_value_store_totals_history_entity_id_from_state_version" ON key_value_store_totals_history (entity_id, from_state_version); + END IF; +END $EF$; + +DO $EF$ +BEGIN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE INDEX "IX_ledger_transaction_markers_entity_id_state_version" ON ledger_transaction_markers (entity_id, state_version) WHERE discriminator = 'event_global_emitter'; END IF; END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE INDEX "IX_ledger_transaction_markers_entity_id_state_version1" ON ledger_transaction_markers (entity_id, state_version) WHERE discriminator = 'affected_global_entity'; END IF; END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE INDEX "IX_ledger_transaction_markers_event_type_entity_id_state_versi~" ON ledger_transaction_markers (event_type, entity_id, state_version) WHERE discriminator = 'event'; END IF; END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE INDEX "IX_ledger_transaction_markers_manifest_class" ON ledger_transaction_markers (manifest_class, state_version) WHERE discriminator = 'manifest_class'; END IF; END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE INDEX "IX_ledger_transaction_markers_manifest_class_is_most_specific" ON ledger_transaction_markers (manifest_class, state_version) WHERE discriminator = 'manifest_class' and is_most_specific = true; END IF; END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE INDEX "IX_ledger_transaction_markers_operation_type_entity_id_state_v~" ON ledger_transaction_markers (operation_type, entity_id, state_version) WHERE discriminator = 'manifest_address'; END IF; END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE INDEX "IX_ledger_transaction_markers_origin_type_state_version" ON ledger_transaction_markers (origin_type, state_version) WHERE discriminator = 'origin'; END IF; END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE INDEX "IX_ledger_transaction_markers_state_version" ON ledger_transaction_markers (state_version); END IF; END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE UNIQUE INDEX "IX_ledger_transactions_epoch_round_in_epoch" ON ledger_transactions (epoch, round_in_epoch) WHERE index_in_round = 0; END IF; END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE INDEX "IX_ledger_transactions_intent_hash" ON ledger_transactions USING hash (intent_hash) WHERE intent_hash IS NOT NULL; END IF; END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE INDEX "IX_ledger_transactions_round_timestamp" ON ledger_transactions (round_timestamp); END IF; END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE INDEX "IX_non_fungible_id_data_history_non_fungible_id_definition_id_~" ON non_fungible_id_data_history (non_fungible_id_definition_id, from_state_version); END IF; END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE INDEX "IX_non_fungible_id_definition_non_fungible_resource_entity_id_~" ON non_fungible_id_definition (non_fungible_resource_entity_id, from_state_version); END IF; END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE UNIQUE INDEX "IX_non_fungible_id_definition_non_fungible_resource_entity_id~1" ON non_fungible_id_definition (non_fungible_resource_entity_id, non_fungible_id, from_state_version); END IF; END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE INDEX "IX_non_fungible_id_location_history_non_fungible_id_definition~" ON non_fungible_id_location_history (non_fungible_id_definition_id, from_state_version); END IF; END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE INDEX "IX_non_fungible_schema_history_resource_entity_id_from_state_v~" ON non_fungible_schema_history (resource_entity_id, from_state_version); END IF; END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE INDEX "IX_non_fungible_vault_entry_definition_vault_entity_id_from_st~" ON non_fungible_vault_entry_definition (vault_entity_id, from_state_version); END IF; END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE INDEX "IX_non_fungible_vault_entry_history_non_fungible_vault_entry_d~" ON non_fungible_vault_entry_history (non_fungible_vault_entry_definition_id, from_state_version); END IF; END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE INDEX "IX_package_blueprint_aggregate_history_package_entity_id_from_~" ON package_blueprint_aggregate_history (package_entity_id, from_state_version); END IF; END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE INDEX "IX_package_blueprint_history_package_entity_id_from_state_vers~" ON package_blueprint_history (package_entity_id, from_state_version); END IF; END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE INDEX "IX_package_blueprint_history_package_entity_id_name_version_fr~" ON package_blueprint_history (package_entity_id, name, version, from_state_version); END IF; END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE INDEX "IX_package_code_aggregate_history_package_entity_id_from_state~" ON package_code_aggregate_history (package_entity_id, from_state_version); END IF; END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE INDEX "IX_package_code_history_package_entity_id_from_state_version" ON package_code_history (package_entity_id, from_state_version); END IF; END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE UNIQUE INDEX "IX_pending_transaction_payloads_pending_transaction_id" ON pending_transaction_payloads (pending_transaction_id); END IF; END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE INDEX "IX_pending_transactions_first_submitted_to_gateway_timestamp" ON pending_transactions (first_submitted_to_gateway_timestamp); END IF; END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE INDEX "IX_pending_transactions_intent_hash" ON pending_transactions (intent_hash); END IF; END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE UNIQUE INDEX "IX_pending_transactions_payload_hash" ON pending_transactions (payload_hash); END IF; END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE INDEX "IX_pending_transactions_resubmit_from_timestamp" ON pending_transactions (resubmit_from_timestamp); END IF; END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE INDEX "IX_resource_entity_supply_history_resource_entity_id_from_stat~" ON resource_entity_supply_history (resource_entity_id, from_state_version); END IF; END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE UNIQUE INDEX "IX_resource_holders_entity_id_resource_entity_id" ON resource_holders (entity_id, resource_entity_id); END IF; END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE INDEX "IX_resource_holders_entity_id_resource_entity_id_balance" ON resource_holders (entity_id, resource_entity_id, balance); END IF; END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE INDEX "IX_schema_entry_aggregate_history_entity_id_from_state_version" ON schema_entry_aggregate_history (entity_id, from_state_version); END IF; END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE INDEX "IX_schema_entry_definition_entity_id_schema_hash" ON schema_entry_definition (entity_id, schema_hash); END IF; END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE INDEX "IX_state_history_entity_id_from_state_version" ON state_history (entity_id, from_state_version); END IF; END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE INDEX "IX_unverified_standard_metadata_aggregate_history_entity_id_fr~" ON unverified_standard_metadata_aggregate_history (entity_id, from_state_version); END IF; END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE INDEX "IX_unverified_standard_metadata_entry_history_entity_id_discri~" ON unverified_standard_metadata_entry_history (entity_id, discriminator, from_state_version); END IF; END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE INDEX "IX_validator_active_set_history_epoch" ON validator_active_set_history (epoch); END IF; END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE INDEX "IX_validator_active_set_history_from_state_version" ON validator_active_set_history (from_state_version); END IF; END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE INDEX "IX_validator_active_set_history_validator_public_key_history_id" ON validator_active_set_history (validator_public_key_history_id); END IF; END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE INDEX "IX_validator_cumulative_emission_history_validator_entity_id_e~" ON validator_cumulative_emission_history (validator_entity_id, epoch_number); END IF; END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE INDEX "IX_validator_cumulative_emission_history_validator_entity_id_f~" ON validator_cumulative_emission_history (validator_entity_id, from_state_version); END IF; END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE INDEX "IX_validator_public_key_history_validator_entity_id_from_state~" ON validator_public_key_history (validator_entity_id, from_state_version); END IF; END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE INDEX "IX_validator_public_key_history_validator_entity_id_key_type_k~" ON validator_public_key_history (validator_entity_id, key_type, key); END IF; END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN CREATE INDEX "IX_vault_balance_history_vault_entity_id_from_state_version" ON vault_balance_history (vault_entity_id, from_state_version); END IF; END $EF$; DO $EF$ BEGIN - IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20240927111052_InitialCreate') THEN + IF NOT EXISTS(SELECT 1 FROM "__EFMigrationsHistory" WHERE "MigrationId" = '20241001130214_InitialCreate') THEN INSERT INTO "__EFMigrationsHistory" ("MigrationId", "ProductVersion") - VALUES ('20240927111052_InitialCreate', '8.0.2'); + VALUES ('20241001130214_InitialCreate', '8.0.2'); END IF; END $EF$; COMMIT; diff --git a/src/RadixDlt.NetworkGateway.PostgresIntegration/Migrations/MigrationsDbContextModelSnapshot.cs b/src/RadixDlt.NetworkGateway.PostgresIntegration/Migrations/MigrationsDbContextModelSnapshot.cs index 37ba7e8a9..569fd91fb 100644 --- a/src/RadixDlt.NetworkGateway.PostgresIntegration/Migrations/MigrationsDbContextModelSnapshot.cs +++ b/src/RadixDlt.NetworkGateway.PostgresIntegration/Migrations/MigrationsDbContextModelSnapshot.cs @@ -992,6 +992,38 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.ToTable("key_value_store_schema_history"); }); + modelBuilder.Entity("RadixDlt.NetworkGateway.PostgresIntegration.Models.KeyValueStoreTotalsHistory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("EntityId") + .HasColumnType("bigint") + .HasColumnName("entity_id"); + + b.Property("FromStateVersion") + .HasColumnType("bigint") + .HasColumnName("from_state_version"); + + b.Property("TotalEntriesExcludingDeleted") + .HasColumnType("bigint") + .HasColumnName("total_entries_excluding_deleted"); + + b.Property("TotalEntriesIncludingDeleted") + .HasColumnType("bigint") + .HasColumnName("total_entries_including_deleted"); + + b.HasKey("Id"); + + b.HasIndex("EntityId", "FromStateVersion"); + + b.ToTable("key_value_store_totals_history"); + }); + modelBuilder.Entity("RadixDlt.NetworkGateway.PostgresIntegration.Models.LedgerTransaction", b => { b.Property("StateVersion") diff --git a/src/RadixDlt.NetworkGateway.PostgresIntegration/Models/KeyValueStore/KeyValueStoreTotalsHistory.cs b/src/RadixDlt.NetworkGateway.PostgresIntegration/Models/KeyValueStore/KeyValueStoreTotalsHistory.cs new file mode 100644 index 000000000..433948926 --- /dev/null +++ b/src/RadixDlt.NetworkGateway.PostgresIntegration/Models/KeyValueStore/KeyValueStoreTotalsHistory.cs @@ -0,0 +1,92 @@ +/* Copyright 2021 Radix Publishing Ltd incorporated in Jersey (Channel Islands). + * + * Licensed under the Radix License, Version 1.0 (the "License"); you may not use this + * file except in compliance with the License. You may obtain a copy of the License at: + * + * radixfoundation.org/licenses/LICENSE-v1 + * + * The Licensor hereby grants permission for the Canonical version of the Work to be + * published, distributed and used under or by reference to the Licensor’s trademark + * Radix ® and use of any unregistered trade names, logos or get-up. + * + * The Licensor provides the Work (and each Contributor provides its Contributions) on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, + * including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, + * MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. + * + * Whilst the Work is capable of being deployed, used and adopted (instantiated) to create + * a distributed ledger it is your responsibility to test and validate the code, together + * with all logic and performance of that code under all foreseeable scenarios. + * + * The Licensor does not make or purport to make and hereby excludes liability for all + * and any representation, warranty or undertaking in any form whatsoever, whether express + * or implied, to any entity or person, including any representation, warranty or + * undertaking, as to the functionality security use, value or other characteristics of + * any distributed ledger nor in respect the functioning or value of any tokens which may + * be created stored or transferred using the Work. The Licensor does not warrant that the + * Work or any use of the Work complies with any law or regulation in any territory where + * it may be implemented or used or that it will be appropriate for any specific purpose. + * + * Neither the licensor nor any current or former employees, officers, directors, partners, + * trustees, representatives, agents, advisors, contractors, or volunteers of the Licensor + * shall be liable for any direct or indirect, special, incidental, consequential or other + * losses of any kind, in tort, contract or otherwise (including but not limited to loss + * of revenue, income or profits, or loss of use or data, or loss of reputation, or loss + * of any economic or other opportunity of whatsoever nature or howsoever arising), arising + * out of or in connection with (without limitation of any use, misuse, of any ledger system + * or use made or its functionality or any performance or operation of any code or protocol + * caused by bugs or programming or logic errors or otherwise); + * + * A. any offer, purchase, holding, use, sale, exchange or transmission of any + * cryptographic keys, tokens or assets created, exchanged, stored or arising from any + * interaction with the Work; + * + * B. any failure in a transmission or loss of any token or assets keys or other digital + * artefacts due to errors in transmission; + * + * C. bugs, hacks, logic errors or faults in the Work or any communication; + * + * D. system software or apparatus including but not limited to losses caused by errors + * in holding or transmitting tokens by any third-party; + * + * E. breaches or failure of security including hacker attacks, loss or disclosure of + * password, loss of private key, unauthorised use or misuse of such passwords or keys; + * + * F. any losses including loss of anticipated savings or other benefits resulting from + * use of the Work or any changes to the Work (however implemented). + * + * You are solely responsible for; testing, validating and evaluation of all operation + * logic, functionality, security and appropriateness of using the Work for any commercial + * or non-commercial purpose and for any reproduction or redistribution by You of the + * Work. You assume all risks associated with Your use of the Work and the exercise of + * permissions under this License. + */ + +// +// Copyright (c) PlaceholderCompany. All rights reserved. +// + +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; + +namespace RadixDlt.NetworkGateway.PostgresIntegration.Models; + +[Table("key_value_store_totals_history")] +internal class KeyValueStoreTotalsHistory +{ + [Key] + [Column("id")] + public long Id { get; set; } + + [Column("from_state_version")] + public long FromStateVersion { get; set; } + + [Column("entity_id")] + public long EntityId { get; set; } + + [Column("total_entries_including_deleted")] + public long TotalEntriesIncludingDeleted { get; set; } + + [Column("total_entries_excluding_deleted")] + public long TotalEntriesExcludingDeleted { get; set; } +} diff --git a/src/RadixDlt.NetworkGateway.PostgresIntegration/Queries/KeyValueStoreQueries.cs b/src/RadixDlt.NetworkGateway.PostgresIntegration/Queries/KeyValueStoreQueries.cs new file mode 100644 index 000000000..f91769245 --- /dev/null +++ b/src/RadixDlt.NetworkGateway.PostgresIntegration/Queries/KeyValueStoreQueries.cs @@ -0,0 +1,366 @@ +// +// Copyright (c) PlaceholderCompany. All rights reserved. +// + +using Dapper; +using Microsoft.EntityFrameworkCore; +using RadixDlt.NetworkGateway.Abstractions; +using RadixDlt.NetworkGateway.Abstractions.Extensions; +using RadixDlt.NetworkGateway.Abstractions.Model; +using RadixDlt.NetworkGateway.PostgresIntegration.Models; +using RadixDlt.NetworkGateway.PostgresIntegration.Queries.CustomTypes; +using RadixDlt.NetworkGateway.PostgresIntegration.Services; +using RadixDlt.NetworkGateway.PostgresIntegration.Utils; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using GatewayModel = RadixDlt.NetworkGateway.GatewayApiSdk.Model; + +namespace RadixDlt.NetworkGateway.PostgresIntegration.Queries; + +internal static class KeyValueStoreQueries +{ + internal readonly record struct KeyValueStoreKeysQueryConfiguration( + GatewayModel.IdBoundaryCoursor? Cursor, + int PageSize, + int MaxDefinitionsLookupLimit + ); + + internal record KeyValueStoreSchemaResultRow( + byte[] KeySchema, + long KeyTypeIndex, + SborTypeKind KeySborTypeKind, + byte[] ValueSchema, + long ValueTypeIndex, + SborTypeKind ValueSborTypeKind); + + private readonly record struct KeyValueStoreKeysResultRow( + long KeyValueStoreEntityId, + long TotalEntriesExcludingDeleted, + long TotalEntriesIncludingDeleted, + long DefinitionId, + byte[] Key, + long KeyFirstSeenStateVersion, + byte[] Value, + bool IsLocked, + bool IsDeleted, + long LastUpdatedStateVersion, + bool FilterOut, + bool IsLastCandidate, + IdBoundaryCursor? NextCursorInclusive + ); + + private readonly record struct KeyValueStoreDataResultRow( + long KeyValueStoreEntityId, + byte[] Key, + long KeyFirstSeenStateVersion, + byte[] Value, + bool IsDeleted, + bool IsLocked, + long LastUpdatedStateVersion, + bool FilterOut); + + internal static async Task KeyValueStoreKeys( + ReadOnlyDbContext dbContext, + IDapperWrapper dapperWrapper, + Entity keyValueStoreEntity, + KeyValueStoreSchemaResultRow schema, + GatewayModel.LedgerState ledgerState, + byte networkId, + KeyValueStoreKeysQueryConfiguration queryConfiguration, + CancellationToken token = default) + { + var cd = new CommandDefinition( + commandText: @" +WITH vars AS ( + SELECT + @keyValueStoreEntityId AS key_value_store_entity_id, + CAST(@useCursor AS bool) AS use_cursor, + ROW(CAST(@cursorStateVersion AS bigint), CAST(@cursorDefinitionId AS bigint)) AS start_cursor_inclusive, + @atLedgerState AS at_ledger_state, + @definitionReadLimit AS definition_read_limit, + @pageLimit as page_limit +), +definitions_with_cursor AS ( + SELECT + d.*, + (d.from_state_version, d.id) AS cursor + FROM key_value_store_entry_definition d +) +SELECT + -- entity data + vars.key_value_store_entity_id AS KeyValueStoreEntityId, + + -- totals + COALESCE(entity_totals.total_entries_excluding_deleted, 0) AS TotalEntriesExcludingDeleted, + COALESCE(entity_totals.total_entries_including_deleted, 0) AS TotalEntriesIncludingDeleted, + + -- entries + CASE WHEN COALESCE(filter_out, TRUE) THEN NULL ELSE entries_per_entity.definition_id END AS DefinitionId, + CASE WHEN COALESCE(filter_out, TRUE) THEN NULL ELSE entries_per_entity.key END AS Key, + CASE WHEN COALESCE(filter_out, TRUE) THEN NULL ELSE entries_per_entity.key_first_seen_state_version END AS KeyFirstSeenStateVersion, + + CASE WHEN COALESCE(filter_out, TRUE) THEN NULL ELSE entries_per_entity.value END AS Value, + CASE WHEN COALESCE(filter_out, TRUE) THEN NULL ELSE entries_per_entity.is_locked END AS IsLocked, + CASE WHEN COALESCE(filter_out, TRUE) THEN NULL ELSE entries_per_entity.is_deleted END AS IsDeleted, + CASE WHEN COALESCE(filter_out, TRUE) THEN NULL ELSE entries_per_entity.last_updated_state_version END AS LastUpdatedStateVersion, + + -- cursor + COALESCE(entries_per_entity.filter_out, TRUE) AS FilterOut, + COALESCE(entries_per_entity.is_last_candidate, TRUE) AS IsLastCandidate, + next_cursor_inclusive AS NextCursorInclusive +FROM vars + + -- Totals + LEFT JOIN LATERAL ( + SELECT + t.total_entries_excluding_deleted AS total_entries_excluding_deleted, + t.total_entries_including_deleted AS total_entries_including_deleted + FROM key_value_store_totals_history t + WHERE t.entity_id = vars.key_value_store_entity_id AND t.from_state_version <= vars.at_ledger_state + ORDER BY t.from_state_version DESC + LIMIT 1 +) entity_totals ON TRUE + +-- entries_per_entity +LEFT JOIN LATERAL ( + SELECT + definitions.id as definition_id, + definitions.key, + definitions.key_first_seen_state_version, + definitions.is_last_candidate, + definitions.cursor, + entries.last_updated_state_version, + entries.value, + entries.is_locked, + entries.is_deleted, + CASE WHEN (ROW_NUMBER() OVER (ORDER BY definitions.cursor DESC)) = vars.page_limit OR entries.filter_out + THEN TRUE + ELSE FALSE + END AS filter_out, + CASE + WHEN (ROW_NUMBER() OVER (ORDER BY definitions.cursor DESC)) = vars.page_limit + THEN definitions.cursor + WHEN (ROW_NUMBER() OVER (ORDER BY definitions.cursor DESC)) != vars.page_limit AND definitions.is_last_candidate + THEN ROW(definitions.key_first_seen_state_version, definitions.id - 1) + END AS next_cursor_inclusive + FROM ( + SELECT + d.id, + d.key, + d.cursor, + d.from_state_version AS key_first_seen_state_version, + (ROW_NUMBER() OVER (ORDER BY d.cursor DESC)) = vars.definition_read_limit AS is_last_candidate + FROM definitions_with_cursor d + WHERE d.key_value_store_entity_id = vars.key_value_store_entity_id AND ((NOT vars.use_cursor) OR d.cursor <= vars.start_cursor_inclusive) + ORDER BY d.cursor DESC + LIMIT vars.definition_read_limit + ) definitions + INNER JOIN LATERAL ( + SELECT + h.from_state_version AS last_updated_state_version, + h.value, + h.is_locked, + h.is_deleted, + h.is_deleted as filter_out + FROM key_value_store_entry_history h + WHERE h.key_value_store_entry_definition_id = definitions.id AND h.from_state_version <= vars.at_ledger_state + ORDER BY h.from_state_version DESC + LIMIT 1 + ) entries ON TRUE + WHERE entries.filter_out = FALSE OR definitions.is_last_candidate + ORDER BY definitions.cursor DESC + LIMIT vars.page_limit +) entries_per_entity ON TRUE +ORDER BY entries_per_entity.cursor DESC +;", + parameters: new + { + keyValueStoreEntityId = keyValueStoreEntity.Id, + atLedgerState = ledgerState.StateVersion, + useCursor = queryConfiguration.Cursor is not null, + cursorStateVersion = queryConfiguration.Cursor?.StateVersionBoundary ?? 0, + cursorDefinitionId = queryConfiguration.Cursor?.IdBoundary ?? 0, + definitionReadLimit = queryConfiguration.MaxDefinitionsLookupLimit, + pageLimit = queryConfiguration.PageSize + 1, + }, + cancellationToken: token); + + var queryResult = (await dapperWrapper.QueryAsync(dbContext.Database.GetDbConnection(), cd)).ToList(); + + var totalEntries = queryResult.First().TotalEntriesExcludingDeleted; + var elementWithCursor = queryResult.SingleOrDefault(x => x.NextCursorInclusive.HasValue); + + var nextCursor = elementWithCursor.NextCursorInclusive != null + ? new GatewayModel.IdBoundaryCoursor( + elementWithCursor.NextCursorInclusive.Value.StateVersion, + elementWithCursor.NextCursorInclusive.Value.Id) + .ToCursorString() + : null; + + var items = queryResult + .Where(x => !x.FilterOut) + .Select( + e => + { + var keyProgrammaticJson = ScryptoSborUtils.DataToProgrammaticJson( + e.Key, + schema.KeySchema, + schema.KeySborTypeKind, + schema.KeyTypeIndex, + networkId); + + return new GatewayModel.StateKeyValueStoreKeysResponseItem( + key: new GatewayModel.ScryptoSborValue(e.Key.ToHex(), keyProgrammaticJson), + lastUpdatedAtStateVersion: e.LastUpdatedStateVersion + ); + }) + .ToList(); + + return new GatewayModel.StateKeyValueStoreKeysResponse( + ledgerState: ledgerState, + keyValueStoreAddress: keyValueStoreEntity.Address, + nextCursor: nextCursor, + items: items, + totalCount: totalEntries + ); + } + + internal static async Task KeyValueStoreData( + ReadOnlyDbContext dbContext, + IDapperWrapper dapperWrapper, + Entity keyValueStoreEntity, + KeyValueStoreSchemaResultRow schema, + IList keys, + byte networkId, + GatewayModel.LedgerState ledgerState, + CancellationToken token = default) + { + var cd = new CommandDefinition( + commandText: @" +WITH vars AS ( + SELECT + @entityId as entity_id, + UNNEST(@keys) as key, + @atLedgerState AS at_ledger_state +) +SELECT + -- entity id + vars.entity_id as EntityId, + + -- data + CASE WHEN COALESCE(entries_with_definitions.filter_out, TRUE) THEN NULL ELSE entries_with_definitions.key END, + CASE WHEN COALESCE(entries_with_definitions.filter_out, TRUE) THEN NULL ELSE entries_with_definitions.KeyFirstSeenStateVersion END, + CASE WHEN COALESCE(entries_with_definitions.filter_out, TRUE) THEN NULL ELSE entries_with_definitions.value END, + CASE WHEN COALESCE(entries_with_definitions.filter_out, TRUE) THEN NULL ELSE entries_with_definitions.is_locked END AS IsLocked, + CASE WHEN COALESCE(entries_with_definitions.filter_out, TRUE) THEN NULL ELSE entries_with_definitions.LastUpdatedStateVersion END, + COALESCE(entries_with_definitions.filter_out, TRUE) AS FilterOut +FROM vars + +-- entries +LEFT JOIN LATERAL ( + SELECT + definition.key, + definition.from_state_version AS KeyFirstSeenStateVersion, + history.value, + history.is_locked, + history.is_deleted AS filter_out, + history.from_state_version AS LastUpdatedStateVersion + FROM key_value_store_entry_definition definition + INNER JOIN LATERAL ( + SELECT + value, + is_locked, + is_deleted, + from_state_version + FROM key_value_store_entry_history history + WHERE history.key_value_store_entry_definition_id = definition.id AND from_state_version <= vars.at_ledger_state + ORDER BY history.from_state_version DESC + LIMIT 1 + ) history on true + WHERE definition.key_value_store_entity_id = vars.entity_id AND definition.key = vars.key +) entries_with_definitions on TRUE", + parameters: new + { + entityId = keyValueStoreEntity.Id, + atLedgerState = ledgerState.StateVersion, + keys = keys.Distinct().Select(k => (byte[])k).ToList(), + }, + cancellationToken: token); + + var queryResult = await dapperWrapper.QueryAsync(dbContext.Database.GetDbConnection(), cd); + + var items = queryResult + .Where(x => !x.FilterOut) + .Select( + x => + { + var keyProgrammaticJson = ScryptoSborUtils.DataToProgrammaticJson( + x.Key, + schema.KeySchema, + schema.KeySborTypeKind, + schema.KeyTypeIndex, + networkId); + var valueProgrammaticJson = ScryptoSborUtils.DataToProgrammaticJson( + x.Value, + schema.ValueSchema, + schema.ValueSborTypeKind, + schema.ValueTypeIndex, + networkId); + + return new GatewayModel.StateKeyValueStoreDataResponseItem( + key: new GatewayModel.ScryptoSborValue(x.Key.ToHex(), keyProgrammaticJson), + value: new GatewayModel.ScryptoSborValue(x.Value.ToHex(), valueProgrammaticJson), + lastUpdatedAtStateVersion: x.LastUpdatedStateVersion, + isLocked: x.IsLocked); + }) + .ToList(); + + return new GatewayModel.StateKeyValueStoreDataResponse(ledgerState, keyValueStoreEntity.Address, items); + } + + internal static async Task KeyValueStoreSchema( + ReadOnlyDbContext dbContext, + IDapperWrapper dapperWrapper, + long keyValueStoreId, + GatewayModel.LedgerState ledgerState, + CancellationToken token = default) + { + var keyValueStoreSchemaQuery = new CommandDefinition( + commandText: @" +SELECT + ksh.schema AS KeySchema, + kvssh.key_type_index AS KeyTypeIndex, + kvssh.key_sbor_type_kind AS KeySborTypeKind, + vsh.schema AS ValueSchema, + kvssh.value_type_index AS ValueTypeIndex, + kvssh.value_sbor_type_kind AS ValueSborTypeKind +FROM key_value_store_schema_history kvssh +INNER JOIN schema_entry_definition ksh ON ksh.schema_hash = kvssh.key_schema_hash AND ksh.entity_id = kvssh.key_schema_defining_entity_id +INNER JOIN schema_entry_definition vsh ON vsh.schema_hash = kvssh.value_schema_hash AND vsh.entity_id = kvssh.value_schema_defining_entity_id +WHERE kvssh.key_value_store_entity_id = @entityId AND kvssh.from_state_version <= @stateVersion +ORDER BY kvssh.from_state_version DESC +", + parameters: new + { + stateVersion = ledgerState.StateVersion, + entityId = keyValueStoreId, + }, + cancellationToken: token); + + var keyValueStoreSchema = await dapperWrapper.QueryFirstOrDefaultAsync( + dbContext.Database.GetDbConnection(), + keyValueStoreSchemaQuery, + "GetKeyValueStoreSchema" + ); + + if (keyValueStoreSchema == null) + { + throw new UnreachableException($"Missing key value store schema for :{keyValueStoreId}"); + } + + return keyValueStoreSchema; + } +} diff --git a/src/RadixDlt.NetworkGateway.PostgresIntegration/Services/KeyValueStoreQuerier.cs b/src/RadixDlt.NetworkGateway.PostgresIntegration/Services/KeyValueStoreQuerier.cs index 6efa48102..c947bea60 100644 --- a/src/RadixDlt.NetworkGateway.PostgresIntegration/Services/KeyValueStoreQuerier.cs +++ b/src/RadixDlt.NetworkGateway.PostgresIntegration/Services/KeyValueStoreQuerier.cs @@ -62,19 +62,14 @@ * permissions under this License. */ -using Dapper; -using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Options; using RadixDlt.NetworkGateway.Abstractions; -using RadixDlt.NetworkGateway.Abstractions.Extensions; -using RadixDlt.NetworkGateway.Abstractions.Model; using RadixDlt.NetworkGateway.Abstractions.Network; +using RadixDlt.NetworkGateway.GatewayApi.Configuration; using RadixDlt.NetworkGateway.GatewayApi.Services; using RadixDlt.NetworkGateway.PostgresIntegration.Models; using RadixDlt.NetworkGateway.PostgresIntegration.Queries; -using RadixDlt.NetworkGateway.PostgresIntegration.Utils; using System.Collections.Generic; -using System.Diagnostics; -using System.Linq; using System.Threading; using System.Threading.Tasks; using GatewayModel = RadixDlt.NetworkGateway.GatewayApiSdk.Model; @@ -83,25 +78,24 @@ namespace RadixDlt.NetworkGateway.PostgresIntegration.Services; internal class KeyValueStoreQuerier : IKeyValueStoreQuerier { - private record KeyValueStoreEntryResultRow(long Id, byte[] Key, long FromStateVersion, byte[] Value, bool IsDeleted, bool IsLocked, long LastUpdatedAtStateVersion); - - private record KeyValueStoreSchemaResultRow(byte[] KeySchema, long KeyTypeIndex, SborTypeKind KeySborTypeKind, byte[] ValueSchema, long ValueTypeIndex, SborTypeKind ValueSborTypeKind); - private readonly IDapperWrapper _dapperWrapper; private readonly ReadOnlyDbContext _dbContext; private readonly INetworkConfigurationProvider _networkConfigurationProvider; private readonly IEntityQuerier _entityQuerier; + private readonly IOptionsSnapshot _endpointConfiguration; public KeyValueStoreQuerier( IDapperWrapper dapperWrapper, ReadOnlyDbContext dbContext, INetworkConfigurationProvider networkConfigurationProvider, - IEntityQuerier entityQuerier) + IEntityQuerier entityQuerier, + IOptionsSnapshot endpointConfiguration) { _dapperWrapper = dapperWrapper; _dbContext = dbContext; _networkConfigurationProvider = networkConfigurationProvider; _entityQuerier = entityQuerier; + _endpointConfiguration = endpointConfiguration; } public async Task KeyValueStoreKeys( @@ -111,70 +105,30 @@ public KeyValueStoreQuerier( int pageSize, CancellationToken token = default) { + var networkId = (await _networkConfigurationProvider.GetNetworkConfiguration(token)).Id; var keyValueStore = await _entityQuerier.GetNonVirtualEntity(_dbContext, keyValueStoreAddress, ledgerState, token); - var keyValueStoreSchema = await GetKeyValueStoreSchema(keyValueStore.Id, ledgerState, token); - var cd = new CommandDefinition( - commandText: @" -SELECT d.id AS Id, d.key AS Key, d.from_state_version AS FromStateVersion, h.value AS Value, h.is_deleted AS IsDeleted, h.is_locked AS IsLocked, h.from_state_version AS LastUpdatedAtStateVersion -FROM key_value_store_entry_definition d -INNER JOIN LATERAL ( - SELECT * - FROM key_value_store_entry_history - WHERE key_value_store_entry_definition_id = d.id AND from_state_version <= @stateVersion - ORDER BY from_state_version DESC - LIMIT 1 -) h ON TRUE -WHERE - d.key_value_store_entity_id = @keyValueStoreEntityId - AND (d.from_state_version, d.id) <= (@cursorStateVersion, @cursorId) - AND d.from_state_version <= @stateVersion - AND h.is_deleted = false -ORDER BY d.from_state_version DESC, d.id DESC -LIMIT @limit -;", - parameters: new + var keyValueStoreSchema = await KeyValueStoreQueries.KeyValueStoreSchema( + _dbContext, + _dapperWrapper, + keyValueStore.Id, + ledgerState, + token); + + return await KeyValueStoreQueries.KeyValueStoreKeys( + _dbContext, + _dapperWrapper, + keyValueStore, + keyValueStoreSchema, + ledgerState, + networkId, + new KeyValueStoreQueries.KeyValueStoreKeysQueryConfiguration { - keyValueStoreEntityId = keyValueStore.Id, - stateVersion = ledgerState.StateVersion, - cursorStateVersion = cursor?.StateVersionBoundary ?? long.MaxValue, - cursorId = cursor?.IdBoundary ?? long.MaxValue, - limit = pageSize + 1, + Cursor = cursor, + MaxDefinitionsLookupLimit = _endpointConfiguration.Value.MaxDefinitionsLookupLimit, + PageSize = pageSize, }, - cancellationToken: token); - - var entriesAndOneMore = (await _dapperWrapper.QueryAsync(_dbContext.Database.GetDbConnection(), cd)).ToList(); - var networkId = (await _networkConfigurationProvider.GetNetworkConfiguration(token)).Id; - - var items = entriesAndOneMore - .Take(pageSize) - .Select( - e => - { - var keyProgrammaticJson = ScryptoSborUtils.DataToProgrammaticJson( - e.Key, - keyValueStoreSchema.KeySchema, - keyValueStoreSchema.KeySborTypeKind, - keyValueStoreSchema.KeyTypeIndex, - networkId); - - return new GatewayModel.StateKeyValueStoreKeysResponseItem( - key: new GatewayModel.ScryptoSborValue(e.Key.ToHex(), keyProgrammaticJson), - lastUpdatedAtStateVersion: e.LastUpdatedAtStateVersion - ); - }) - .ToList(); - - var nextCursor = entriesAndOneMore.Count == pageSize + 1 - ? new GatewayModel.IdBoundaryCoursor(entriesAndOneMore.Last().FromStateVersion, entriesAndOneMore.Last().Id).ToCursorString() - : null; - - return new GatewayModel.StateKeyValueStoreKeysResponse( - ledgerState: ledgerState, - keyValueStoreAddress: keyValueStoreAddress, - nextCursor: nextCursor, - items: items - ); + token); } public async Task KeyValueStoreData( @@ -183,101 +137,24 @@ LIMIT @limit GatewayModel.LedgerState ledgerState, CancellationToken token = default) { + var networkId = (await _networkConfigurationProvider.GetNetworkConfiguration(token)).Id; var keyValueStore = await _entityQuerier.GetNonVirtualEntity(_dbContext, keyValueStoreAddress, ledgerState, token); - var keyValueStoreSchema = await GetKeyValueStoreSchema(keyValueStore.Id, ledgerState, token); - - var cd = new CommandDefinition( - commandText: @" -SELECT d.id AS Id, d.key AS Key, d.from_state_version AS FromStateVersion, h.value AS Value, h.is_deleted AS IsDeleted, h.is_locked AS IsLocked, h.from_state_version AS LastUpdatedAtStateVersion -FROM key_value_store_entry_definition d -INNER JOIN LATERAL ( - SELECT * - FROM key_value_store_entry_history - WHERE key_value_store_entry_definition_id = d.id AND from_state_version <= @stateVersion - ORDER BY from_state_version DESC - LIMIT 1 -) h ON TRUE -WHERE d.key_value_store_entity_id = @keyValueStoreEntityId AND d.key = ANY(@keys) AND d.from_state_version <= @stateVersion", - parameters: new - { - stateVersion = ledgerState.StateVersion, - keyValueStoreEntityId = keyValueStore.Id, - keys = keys.Distinct().Select(k => (byte[])k).ToList(), - }, - cancellationToken: token); - - var items = new List(); - - foreach (var e in await _dapperWrapper.QueryAsync(_dbContext.Database.GetDbConnection(), cd)) - { - if (e.IsDeleted) - { - continue; - } - - var networkId = (await _networkConfigurationProvider.GetNetworkConfiguration(token)).Id; - var keyProgrammaticJson = ScryptoSborUtils.DataToProgrammaticJson( - e.Key, - keyValueStoreSchema.KeySchema, - keyValueStoreSchema.KeySborTypeKind, - keyValueStoreSchema.KeyTypeIndex, - networkId); - var valueProgrammaticJson = ScryptoSborUtils.DataToProgrammaticJson( - e.Value, - keyValueStoreSchema.ValueSchema, - keyValueStoreSchema.ValueSborTypeKind, - keyValueStoreSchema.ValueTypeIndex, - networkId); - - items.Add( - new GatewayModel.StateKeyValueStoreDataResponseItem( - key: new GatewayModel.ScryptoSborValue(e.Key.ToHex(), keyProgrammaticJson), - value: new GatewayModel.ScryptoSborValue(e.Value.ToHex(), valueProgrammaticJson), - lastUpdatedAtStateVersion: e.LastUpdatedAtStateVersion, - isLocked: e.IsLocked)); - } - - return new GatewayModel.StateKeyValueStoreDataResponse(ledgerState, keyValueStoreAddress, items); - } - - private async Task GetKeyValueStoreSchema( - long keyValueStoreId, - GatewayModel.LedgerState ledgerState, - CancellationToken token = default) - { - var keyValueStoreSchemaQuery = new CommandDefinition( - commandText: @" -SELECT - ksh.schema AS KeySchema, - kvssh.key_type_index AS KeyTypeIndex, - kvssh.key_sbor_type_kind AS KeySborTypeKind, - vsh.schema AS ValueSchema, - kvssh.value_type_index AS ValueTypeIndex, - kvssh.value_sbor_type_kind AS ValueSborTypeKind -FROM key_value_store_schema_history kvssh -INNER JOIN schema_entry_definition ksh ON ksh.schema_hash = kvssh.key_schema_hash AND ksh.entity_id = kvssh.key_schema_defining_entity_id -INNER JOIN schema_entry_definition vsh ON vsh.schema_hash = kvssh.value_schema_hash AND vsh.entity_id = kvssh.value_schema_defining_entity_id -WHERE kvssh.key_value_store_entity_id = @entityId AND kvssh.from_state_version <= @stateVersion -ORDER BY kvssh.from_state_version DESC -", - parameters: new - { - stateVersion = ledgerState.StateVersion, - entityId = keyValueStoreId, - }, - cancellationToken: token); - - var keyValueStoreSchema = await _dapperWrapper.QueryFirstOrDefaultAsync( - _dbContext.Database.GetDbConnection(), - keyValueStoreSchemaQuery, - "GetKeyValueStoreSchema" - ); - - if (keyValueStoreSchema == null) - { - throw new UnreachableException($"Missing key value store schema for :{keyValueStoreId}"); - } - return keyValueStoreSchema; + var keyValueStoreSchema = await KeyValueStoreQueries.KeyValueStoreSchema( + _dbContext, + _dapperWrapper, + keyValueStore.Id, + ledgerState, + token); + + return await KeyValueStoreQueries.KeyValueStoreData( + _dbContext, + _dapperWrapper, + keyValueStore, + keyValueStoreSchema, + keys, + networkId, + ledgerState, + token); } } From 967dfe38c1fe82c38d77e3770e43e7ab1f047cd7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Pawelec?= Date: Thu, 19 Sep 2024 13:16:00 +0200 Subject: [PATCH 2/3] fix total_count for validators endpoint. Removed total_count from transaction stream endpoint and cursor mixin for endpoints that aren't using it. --- CHANGELOG.md | 4 + .../gateway-api-schema.yaml | 41 ++-- .../Model/StreamTransactionsResponse.cs | 21 +- .../Model/StreamTransactionsResponseAllOf.cs | 21 +- .../Model/TwoWayLinkedDappsCollection.cs | 40 +--- .../Model/TwoWayLinkedDappsCollectionAllOf.cs | 194 ------------------ .../Model/TwoWayLinkedEntitiesCollection.cs | 40 +--- .../TwoWayLinkedEntitiesCollectionAllOf.cs | 194 ------------------ .../IoC/GatewayApiBuilderExtensions.cs | 1 + .../LedgerExtension/AccountLockerProcessor.cs | 49 +++-- .../Queries/KeyValueStoreQueries.cs | 66 +++++- .../DepositPreValidationQuerier.cs | 10 +- .../Services/AccountLockerQuerier.cs | 9 +- .../Services/ValidatorQuerier.cs | 10 +- 14 files changed, 162 insertions(+), 538 deletions(-) delete mode 100644 src/RadixDlt.NetworkGateway.GatewayApiSdk/generated/Model/TwoWayLinkedDappsCollectionAllOf.cs delete mode 100644 src/RadixDlt.NetworkGateway.GatewayApiSdk/generated/Model/TwoWayLinkedEntitiesCollectionAllOf.cs diff --git a/CHANGELOG.md b/CHANGELOG.md index 349674ee3..f3aadab3e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,6 +27,10 @@ Release built: _not released yet_ > - `/state/entity/page/non-fungibles/` (when using `non_fungible_include_nfids` opt-in) > - `/state/entity/page/non-fungible-vaults/` (when using `non_fungible_include_nfids` opt-in) + +### Bug fixes + +- Added missing `total_count` property to `/state/validators/list` response. ### API Changes - Restored previously removed `total_count` property to `/state/key-value-store/keys` endpoint. diff --git a/src/RadixDlt.NetworkGateway.GatewayApi/gateway-api-schema.yaml b/src/RadixDlt.NetworkGateway.GatewayApi/gateway-api-schema.yaml index 78ffef8eb..bb4806922 100644 --- a/src/RadixDlt.NetworkGateway.GatewayApi/gateway-api-schema.yaml +++ b/src/RadixDlt.NetworkGateway.GatewayApi/gateway-api-schema.yaml @@ -2317,16 +2317,14 @@ components: TwoWayLinkedDappsCollection: description: A collection of two-way linked (resolved & verified) dApps linked to the entity defining this collection. - allOf: - - $ref: "#/components/schemas/ResultSetCursorMixin" - - type: object - required: - - items - properties: - items: - type: array - items: - $ref: "#/components/schemas/TwoWayLinkedDappsCollectionItem" + type: object + required: + - items + properties: + items: + type: array + items: + $ref: "#/components/schemas/TwoWayLinkedDappsCollectionItem" TwoWayLinkedDappsCollectionItem: type: object required: @@ -2337,16 +2335,14 @@ components: TwoWayLinkedEntitiesCollection: description: A collection of two-way linked (resolved & verified) entities linked to the entity defining this collection. - allOf: - - $ref: "#/components/schemas/ResultSetCursorMixin" - - type: object - required: - - items - properties: - items: - type: array - items: - $ref: "#/components/schemas/TwoWayLinkedEntitiesCollectionItem" + type: object + required: + - items + properties: + items: + type: array + items: + $ref: "#/components/schemas/TwoWayLinkedEntitiesCollectionItem" TwoWayLinkedEntitiesCollectionItem: type: object required: @@ -4055,11 +4051,14 @@ components: StreamTransactionsResponse: allOf: - $ref: "#/components/schemas/LedgerStateMixin" - - $ref: "#/components/schemas/ResultSetCursorMixin" - type: object required: - items properties: + next_cursor: + description: If specified, contains a cursor to query next page of the `items` collection. + type: string + nullable: true items: description: The page of user transactions. type: array diff --git a/src/RadixDlt.NetworkGateway.GatewayApiSdk/generated/Model/StreamTransactionsResponse.cs b/src/RadixDlt.NetworkGateway.GatewayApiSdk/generated/Model/StreamTransactionsResponse.cs index 97e4c63c1..5ad534fdb 100644 --- a/src/RadixDlt.NetworkGateway.GatewayApiSdk/generated/Model/StreamTransactionsResponse.cs +++ b/src/RadixDlt.NetworkGateway.GatewayApiSdk/generated/Model/StreamTransactionsResponse.cs @@ -104,10 +104,9 @@ protected StreamTransactionsResponse() { } /// Initializes a new instance of the class. /// /// ledgerState (required). - /// Total number of items in underlying collection, fragment of which is available in `items` collection.. /// If specified, contains a cursor to query next page of the `items` collection.. /// The page of user transactions. (required). - public StreamTransactionsResponse(LedgerState ledgerState = default(LedgerState), long? totalCount = default(long?), string nextCursor = default(string), List items = default(List)) + public StreamTransactionsResponse(LedgerState ledgerState = default(LedgerState), string nextCursor = default(string), List items = default(List)) { // to ensure "ledgerState" is required (not null) if (ledgerState == null) @@ -121,7 +120,6 @@ protected StreamTransactionsResponse() { } throw new ArgumentNullException("items is a required property for StreamTransactionsResponse and cannot be null"); } this.Items = items; - this.TotalCount = totalCount; this.NextCursor = nextCursor; } @@ -131,13 +129,6 @@ protected StreamTransactionsResponse() { } [DataMember(Name = "ledger_state", IsRequired = true, EmitDefaultValue = true)] public LedgerState LedgerState { get; set; } - /// - /// Total number of items in underlying collection, fragment of which is available in `items` collection. - /// - /// Total number of items in underlying collection, fragment of which is available in `items` collection. - [DataMember(Name = "total_count", EmitDefaultValue = true)] - public long? TotalCount { get; set; } - /// /// If specified, contains a cursor to query next page of the `items` collection. /// @@ -161,7 +152,6 @@ public override string ToString() StringBuilder sb = new StringBuilder(); sb.Append("class StreamTransactionsResponse {\n"); sb.Append(" LedgerState: ").Append(LedgerState).Append("\n"); - sb.Append(" TotalCount: ").Append(TotalCount).Append("\n"); sb.Append(" NextCursor: ").Append(NextCursor).Append("\n"); sb.Append(" Items: ").Append(Items).Append("\n"); sb.Append("}\n"); @@ -204,11 +194,6 @@ public bool Equals(StreamTransactionsResponse input) (this.LedgerState != null && this.LedgerState.Equals(input.LedgerState)) ) && - ( - this.TotalCount == input.TotalCount || - (this.TotalCount != null && - this.TotalCount.Equals(input.TotalCount)) - ) && ( this.NextCursor == input.NextCursor || (this.NextCursor != null && @@ -235,10 +220,6 @@ public override int GetHashCode() { hashCode = (hashCode * 59) + this.LedgerState.GetHashCode(); } - if (this.TotalCount != null) - { - hashCode = (hashCode * 59) + this.TotalCount.GetHashCode(); - } if (this.NextCursor != null) { hashCode = (hashCode * 59) + this.NextCursor.GetHashCode(); diff --git a/src/RadixDlt.NetworkGateway.GatewayApiSdk/generated/Model/StreamTransactionsResponseAllOf.cs b/src/RadixDlt.NetworkGateway.GatewayApiSdk/generated/Model/StreamTransactionsResponseAllOf.cs index 0cc7b7ff1..bbe4a36fe 100644 --- a/src/RadixDlt.NetworkGateway.GatewayApiSdk/generated/Model/StreamTransactionsResponseAllOf.cs +++ b/src/RadixDlt.NetworkGateway.GatewayApiSdk/generated/Model/StreamTransactionsResponseAllOf.cs @@ -103,8 +103,9 @@ protected StreamTransactionsResponseAllOf() { } /// /// Initializes a new instance of the class. /// + /// If specified, contains a cursor to query next page of the `items` collection.. /// The page of user transactions. (required). - public StreamTransactionsResponseAllOf(List items = default(List)) + public StreamTransactionsResponseAllOf(string nextCursor = default(string), List items = default(List)) { // to ensure "items" is required (not null) if (items == null) @@ -112,8 +113,16 @@ protected StreamTransactionsResponseAllOf() { } throw new ArgumentNullException("items is a required property for StreamTransactionsResponseAllOf and cannot be null"); } this.Items = items; + this.NextCursor = nextCursor; } + /// + /// If specified, contains a cursor to query next page of the `items` collection. + /// + /// If specified, contains a cursor to query next page of the `items` collection. + [DataMember(Name = "next_cursor", EmitDefaultValue = true)] + public string NextCursor { get; set; } + /// /// The page of user transactions. /// @@ -129,6 +138,7 @@ public override string ToString() { StringBuilder sb = new StringBuilder(); sb.Append("class StreamTransactionsResponseAllOf {\n"); + sb.Append(" NextCursor: ").Append(NextCursor).Append("\n"); sb.Append(" Items: ").Append(Items).Append("\n"); sb.Append("}\n"); return sb.ToString(); @@ -165,6 +175,11 @@ public bool Equals(StreamTransactionsResponseAllOf input) return false; } return + ( + this.NextCursor == input.NextCursor || + (this.NextCursor != null && + this.NextCursor.Equals(input.NextCursor)) + ) && ( this.Items == input.Items || this.Items != null && @@ -182,6 +197,10 @@ public override int GetHashCode() unchecked // Overflow is fine, just wrap { int hashCode = 41; + if (this.NextCursor != null) + { + hashCode = (hashCode * 59) + this.NextCursor.GetHashCode(); + } if (this.Items != null) { hashCode = (hashCode * 59) + this.Items.GetHashCode(); diff --git a/src/RadixDlt.NetworkGateway.GatewayApiSdk/generated/Model/TwoWayLinkedDappsCollection.cs b/src/RadixDlt.NetworkGateway.GatewayApiSdk/generated/Model/TwoWayLinkedDappsCollection.cs index d7eed451e..f38933200 100644 --- a/src/RadixDlt.NetworkGateway.GatewayApiSdk/generated/Model/TwoWayLinkedDappsCollection.cs +++ b/src/RadixDlt.NetworkGateway.GatewayApiSdk/generated/Model/TwoWayLinkedDappsCollection.cs @@ -103,10 +103,8 @@ protected TwoWayLinkedDappsCollection() { } /// /// Initializes a new instance of the class. /// - /// Total number of items in underlying collection, fragment of which is available in `items` collection.. - /// If specified, contains a cursor to query next page of the `items` collection.. /// items (required). - public TwoWayLinkedDappsCollection(long? totalCount = default(long?), string nextCursor = default(string), List items = default(List)) + public TwoWayLinkedDappsCollection(List items = default(List)) { // to ensure "items" is required (not null) if (items == null) @@ -114,24 +112,8 @@ protected TwoWayLinkedDappsCollection() { } throw new ArgumentNullException("items is a required property for TwoWayLinkedDappsCollection and cannot be null"); } this.Items = items; - this.TotalCount = totalCount; - this.NextCursor = nextCursor; } - /// - /// Total number of items in underlying collection, fragment of which is available in `items` collection. - /// - /// Total number of items in underlying collection, fragment of which is available in `items` collection. - [DataMember(Name = "total_count", EmitDefaultValue = true)] - public long? TotalCount { get; set; } - - /// - /// If specified, contains a cursor to query next page of the `items` collection. - /// - /// If specified, contains a cursor to query next page of the `items` collection. - [DataMember(Name = "next_cursor", EmitDefaultValue = true)] - public string NextCursor { get; set; } - /// /// Gets or Sets Items /// @@ -146,8 +128,6 @@ public override string ToString() { StringBuilder sb = new StringBuilder(); sb.Append("class TwoWayLinkedDappsCollection {\n"); - sb.Append(" TotalCount: ").Append(TotalCount).Append("\n"); - sb.Append(" NextCursor: ").Append(NextCursor).Append("\n"); sb.Append(" Items: ").Append(Items).Append("\n"); sb.Append("}\n"); return sb.ToString(); @@ -184,16 +164,6 @@ public bool Equals(TwoWayLinkedDappsCollection input) return false; } return - ( - this.TotalCount == input.TotalCount || - (this.TotalCount != null && - this.TotalCount.Equals(input.TotalCount)) - ) && - ( - this.NextCursor == input.NextCursor || - (this.NextCursor != null && - this.NextCursor.Equals(input.NextCursor)) - ) && ( this.Items == input.Items || this.Items != null && @@ -211,14 +181,6 @@ public override int GetHashCode() unchecked // Overflow is fine, just wrap { int hashCode = 41; - if (this.TotalCount != null) - { - hashCode = (hashCode * 59) + this.TotalCount.GetHashCode(); - } - if (this.NextCursor != null) - { - hashCode = (hashCode * 59) + this.NextCursor.GetHashCode(); - } if (this.Items != null) { hashCode = (hashCode * 59) + this.Items.GetHashCode(); diff --git a/src/RadixDlt.NetworkGateway.GatewayApiSdk/generated/Model/TwoWayLinkedDappsCollectionAllOf.cs b/src/RadixDlt.NetworkGateway.GatewayApiSdk/generated/Model/TwoWayLinkedDappsCollectionAllOf.cs deleted file mode 100644 index 01d73438a..000000000 --- a/src/RadixDlt.NetworkGateway.GatewayApiSdk/generated/Model/TwoWayLinkedDappsCollectionAllOf.cs +++ /dev/null @@ -1,194 +0,0 @@ -/* Copyright 2021 Radix Publishing Ltd incorporated in Jersey (Channel Islands). - * - * Licensed under the Radix License, Version 1.0 (the "License"); you may not use this - * file except in compliance with the License. You may obtain a copy of the License at: - * - * radixfoundation.org/licenses/LICENSE-v1 - * - * The Licensor hereby grants permission for the Canonical version of the Work to be - * published, distributed and used under or by reference to the Licensor’s trademark - * Radix ® and use of any unregistered trade names, logos or get-up. - * - * The Licensor provides the Work (and each Contributor provides its Contributions) on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, - * including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, - * MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. - * - * Whilst the Work is capable of being deployed, used and adopted (instantiated) to create - * a distributed ledger it is your responsibility to test and validate the code, together - * with all logic and performance of that code under all foreseeable scenarios. - * - * The Licensor does not make or purport to make and hereby excludes liability for all - * and any representation, warranty or undertaking in any form whatsoever, whether express - * or implied, to any entity or person, including any representation, warranty or - * undertaking, as to the functionality security use, value or other characteristics of - * any distributed ledger nor in respect the functioning or value of any tokens which may - * be created stored or transferred using the Work. The Licensor does not warrant that the - * Work or any use of the Work complies with any law or regulation in any territory where - * it may be implemented or used or that it will be appropriate for any specific purpose. - * - * Neither the licensor nor any current or former employees, officers, directors, partners, - * trustees, representatives, agents, advisors, contractors, or volunteers of the Licensor - * shall be liable for any direct or indirect, special, incidental, consequential or other - * losses of any kind, in tort, contract or otherwise (including but not limited to loss - * of revenue, income or profits, or loss of use or data, or loss of reputation, or loss - * of any economic or other opportunity of whatsoever nature or howsoever arising), arising - * out of or in connection with (without limitation of any use, misuse, of any ledger system - * or use made or its functionality or any performance or operation of any code or protocol - * caused by bugs or programming or logic errors or otherwise); - * - * A. any offer, purchase, holding, use, sale, exchange or transmission of any - * cryptographic keys, tokens or assets created, exchanged, stored or arising from any - * interaction with the Work; - * - * B. any failure in a transmission or loss of any token or assets keys or other digital - * artefacts due to errors in transmission; - * - * C. bugs, hacks, logic errors or faults in the Work or any communication; - * - * D. system software or apparatus including but not limited to losses caused by errors - * in holding or transmitting tokens by any third-party; - * - * E. breaches or failure of security including hacker attacks, loss or disclosure of - * password, loss of private key, unauthorised use or misuse of such passwords or keys; - * - * F. any losses including loss of anticipated savings or other benefits resulting from - * use of the Work or any changes to the Work (however implemented). - * - * You are solely responsible for; testing, validating and evaluation of all operation - * logic, functionality, security and appropriateness of using the Work for any commercial - * or non-commercial purpose and for any reproduction or redistribution by You of the - * Work. You assume all risks associated with Your use of the Work and the exercise of - * permissions under this License. - */ - -/* - * Radix Gateway API - Babylon - * - * This API is exposed by the Babylon Radix Gateway to enable clients to efficiently query current and historic state on the RadixDLT ledger, and intelligently handle transaction submission. It is designed for use by wallets and explorers, and for light queries from front-end dApps. For exchange/asset integrations, back-end dApp integrations, or simple use cases, you should consider using the Core API on a Node. A Gateway is only needed for reading historic snapshots of ledger states or a more robust set-up. The Gateway API is implemented by the [Network Gateway](https://github.com/radixdlt/babylon-gateway), which is configured to read from [full node(s)](https://github.com/radixdlt/babylon-node) to extract and index data from the network. This document is an API reference documentation, visit [User Guide](https://docs.radixdlt.com/) to learn more about how to run a Gateway of your own. ## Migration guide Please see [the latest release notes](https://github.com/radixdlt/babylon-gateway/releases). ## Integration and forward compatibility guarantees All responses may have additional fields added at any release, so clients are advised to use JSON parsers which ignore unknown fields on JSON objects. When the Radix protocol is updated, new functionality may be added, and so discriminated unions returned by the API may need to be updated to have new variants added, corresponding to the updated data. Clients may need to update in advance to be able to handle these new variants when a protocol update comes out. On the very rare occasions we need to make breaking changes to the API, these will be warned in advance with deprecation notices on previous versions. These deprecation notices will include a safe migration path. Deprecation notes or breaking changes will be flagged clearly in release notes for new versions of the Gateway. The Gateway DB schema is not subject to any compatibility guarantees, and may be changed at any release. DB changes will be flagged in the release notes so clients doing custom DB integrations can prepare. - * - * The version of the OpenAPI document: v1.8.0 - * Generated by: https://github.com/openapitools/openapi-generator.git - */ - - -using System; -using System.Collections; -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Linq; -using System.IO; -using System.Runtime.Serialization; -using System.Text; -using System.Text.RegularExpressions; -using Newtonsoft.Json; -using Newtonsoft.Json.Converters; -using Newtonsoft.Json.Linq; -using FileParameter = RadixDlt.NetworkGateway.GatewayApiSdk.Client.FileParameter; -using OpenAPIDateConverter = RadixDlt.NetworkGateway.GatewayApiSdk.Client.OpenAPIDateConverter; - -namespace RadixDlt.NetworkGateway.GatewayApiSdk.Model -{ - /// - /// TwoWayLinkedDappsCollectionAllOf - /// - [DataContract(Name = "TwoWayLinkedDappsCollection_allOf")] - public partial class TwoWayLinkedDappsCollectionAllOf : IEquatable - { - /// - /// Initializes a new instance of the class. - /// - [JsonConstructorAttribute] - protected TwoWayLinkedDappsCollectionAllOf() { } - /// - /// Initializes a new instance of the class. - /// - /// items (required). - public TwoWayLinkedDappsCollectionAllOf(List items = default(List)) - { - // to ensure "items" is required (not null) - if (items == null) - { - throw new ArgumentNullException("items is a required property for TwoWayLinkedDappsCollectionAllOf and cannot be null"); - } - this.Items = items; - } - - /// - /// Gets or Sets Items - /// - [DataMember(Name = "items", IsRequired = true, EmitDefaultValue = true)] - public List Items { get; set; } - - /// - /// Returns the string presentation of the object - /// - /// String presentation of the object - public override string ToString() - { - StringBuilder sb = new StringBuilder(); - sb.Append("class TwoWayLinkedDappsCollectionAllOf {\n"); - sb.Append(" Items: ").Append(Items).Append("\n"); - sb.Append("}\n"); - return sb.ToString(); - } - - /// - /// Returns the JSON string presentation of the object - /// - /// JSON string presentation of the object - public virtual string ToJson() - { - return Newtonsoft.Json.JsonConvert.SerializeObject(this, Newtonsoft.Json.Formatting.Indented); - } - - /// - /// Returns true if objects are equal - /// - /// Object to be compared - /// Boolean - public override bool Equals(object input) - { - return this.Equals(input as TwoWayLinkedDappsCollectionAllOf); - } - - /// - /// Returns true if TwoWayLinkedDappsCollectionAllOf instances are equal - /// - /// Instance of TwoWayLinkedDappsCollectionAllOf to be compared - /// Boolean - public bool Equals(TwoWayLinkedDappsCollectionAllOf input) - { - if (input == null) - { - return false; - } - return - ( - this.Items == input.Items || - this.Items != null && - input.Items != null && - this.Items.SequenceEqual(input.Items) - ); - } - - /// - /// Gets the hash code - /// - /// Hash code - public override int GetHashCode() - { - unchecked // Overflow is fine, just wrap - { - int hashCode = 41; - if (this.Items != null) - { - hashCode = (hashCode * 59) + this.Items.GetHashCode(); - } - return hashCode; - } - } - - } - -} diff --git a/src/RadixDlt.NetworkGateway.GatewayApiSdk/generated/Model/TwoWayLinkedEntitiesCollection.cs b/src/RadixDlt.NetworkGateway.GatewayApiSdk/generated/Model/TwoWayLinkedEntitiesCollection.cs index 40461e430..7a46baeec 100644 --- a/src/RadixDlt.NetworkGateway.GatewayApiSdk/generated/Model/TwoWayLinkedEntitiesCollection.cs +++ b/src/RadixDlt.NetworkGateway.GatewayApiSdk/generated/Model/TwoWayLinkedEntitiesCollection.cs @@ -103,10 +103,8 @@ protected TwoWayLinkedEntitiesCollection() { } /// /// Initializes a new instance of the class. /// - /// Total number of items in underlying collection, fragment of which is available in `items` collection.. - /// If specified, contains a cursor to query next page of the `items` collection.. /// items (required). - public TwoWayLinkedEntitiesCollection(long? totalCount = default(long?), string nextCursor = default(string), List items = default(List)) + public TwoWayLinkedEntitiesCollection(List items = default(List)) { // to ensure "items" is required (not null) if (items == null) @@ -114,24 +112,8 @@ protected TwoWayLinkedEntitiesCollection() { } throw new ArgumentNullException("items is a required property for TwoWayLinkedEntitiesCollection and cannot be null"); } this.Items = items; - this.TotalCount = totalCount; - this.NextCursor = nextCursor; } - /// - /// Total number of items in underlying collection, fragment of which is available in `items` collection. - /// - /// Total number of items in underlying collection, fragment of which is available in `items` collection. - [DataMember(Name = "total_count", EmitDefaultValue = true)] - public long? TotalCount { get; set; } - - /// - /// If specified, contains a cursor to query next page of the `items` collection. - /// - /// If specified, contains a cursor to query next page of the `items` collection. - [DataMember(Name = "next_cursor", EmitDefaultValue = true)] - public string NextCursor { get; set; } - /// /// Gets or Sets Items /// @@ -146,8 +128,6 @@ public override string ToString() { StringBuilder sb = new StringBuilder(); sb.Append("class TwoWayLinkedEntitiesCollection {\n"); - sb.Append(" TotalCount: ").Append(TotalCount).Append("\n"); - sb.Append(" NextCursor: ").Append(NextCursor).Append("\n"); sb.Append(" Items: ").Append(Items).Append("\n"); sb.Append("}\n"); return sb.ToString(); @@ -184,16 +164,6 @@ public bool Equals(TwoWayLinkedEntitiesCollection input) return false; } return - ( - this.TotalCount == input.TotalCount || - (this.TotalCount != null && - this.TotalCount.Equals(input.TotalCount)) - ) && - ( - this.NextCursor == input.NextCursor || - (this.NextCursor != null && - this.NextCursor.Equals(input.NextCursor)) - ) && ( this.Items == input.Items || this.Items != null && @@ -211,14 +181,6 @@ public override int GetHashCode() unchecked // Overflow is fine, just wrap { int hashCode = 41; - if (this.TotalCount != null) - { - hashCode = (hashCode * 59) + this.TotalCount.GetHashCode(); - } - if (this.NextCursor != null) - { - hashCode = (hashCode * 59) + this.NextCursor.GetHashCode(); - } if (this.Items != null) { hashCode = (hashCode * 59) + this.Items.GetHashCode(); diff --git a/src/RadixDlt.NetworkGateway.GatewayApiSdk/generated/Model/TwoWayLinkedEntitiesCollectionAllOf.cs b/src/RadixDlt.NetworkGateway.GatewayApiSdk/generated/Model/TwoWayLinkedEntitiesCollectionAllOf.cs deleted file mode 100644 index f620b0d05..000000000 --- a/src/RadixDlt.NetworkGateway.GatewayApiSdk/generated/Model/TwoWayLinkedEntitiesCollectionAllOf.cs +++ /dev/null @@ -1,194 +0,0 @@ -/* Copyright 2021 Radix Publishing Ltd incorporated in Jersey (Channel Islands). - * - * Licensed under the Radix License, Version 1.0 (the "License"); you may not use this - * file except in compliance with the License. You may obtain a copy of the License at: - * - * radixfoundation.org/licenses/LICENSE-v1 - * - * The Licensor hereby grants permission for the Canonical version of the Work to be - * published, distributed and used under or by reference to the Licensor’s trademark - * Radix ® and use of any unregistered trade names, logos or get-up. - * - * The Licensor provides the Work (and each Contributor provides its Contributions) on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, - * including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, - * MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. - * - * Whilst the Work is capable of being deployed, used and adopted (instantiated) to create - * a distributed ledger it is your responsibility to test and validate the code, together - * with all logic and performance of that code under all foreseeable scenarios. - * - * The Licensor does not make or purport to make and hereby excludes liability for all - * and any representation, warranty or undertaking in any form whatsoever, whether express - * or implied, to any entity or person, including any representation, warranty or - * undertaking, as to the functionality security use, value or other characteristics of - * any distributed ledger nor in respect the functioning or value of any tokens which may - * be created stored or transferred using the Work. The Licensor does not warrant that the - * Work or any use of the Work complies with any law or regulation in any territory where - * it may be implemented or used or that it will be appropriate for any specific purpose. - * - * Neither the licensor nor any current or former employees, officers, directors, partners, - * trustees, representatives, agents, advisors, contractors, or volunteers of the Licensor - * shall be liable for any direct or indirect, special, incidental, consequential or other - * losses of any kind, in tort, contract or otherwise (including but not limited to loss - * of revenue, income or profits, or loss of use or data, or loss of reputation, or loss - * of any economic or other opportunity of whatsoever nature or howsoever arising), arising - * out of or in connection with (without limitation of any use, misuse, of any ledger system - * or use made or its functionality or any performance or operation of any code or protocol - * caused by bugs or programming or logic errors or otherwise); - * - * A. any offer, purchase, holding, use, sale, exchange or transmission of any - * cryptographic keys, tokens or assets created, exchanged, stored or arising from any - * interaction with the Work; - * - * B. any failure in a transmission or loss of any token or assets keys or other digital - * artefacts due to errors in transmission; - * - * C. bugs, hacks, logic errors or faults in the Work or any communication; - * - * D. system software or apparatus including but not limited to losses caused by errors - * in holding or transmitting tokens by any third-party; - * - * E. breaches or failure of security including hacker attacks, loss or disclosure of - * password, loss of private key, unauthorised use or misuse of such passwords or keys; - * - * F. any losses including loss of anticipated savings or other benefits resulting from - * use of the Work or any changes to the Work (however implemented). - * - * You are solely responsible for; testing, validating and evaluation of all operation - * logic, functionality, security and appropriateness of using the Work for any commercial - * or non-commercial purpose and for any reproduction or redistribution by You of the - * Work. You assume all risks associated with Your use of the Work and the exercise of - * permissions under this License. - */ - -/* - * Radix Gateway API - Babylon - * - * This API is exposed by the Babylon Radix Gateway to enable clients to efficiently query current and historic state on the RadixDLT ledger, and intelligently handle transaction submission. It is designed for use by wallets and explorers, and for light queries from front-end dApps. For exchange/asset integrations, back-end dApp integrations, or simple use cases, you should consider using the Core API on a Node. A Gateway is only needed for reading historic snapshots of ledger states or a more robust set-up. The Gateway API is implemented by the [Network Gateway](https://github.com/radixdlt/babylon-gateway), which is configured to read from [full node(s)](https://github.com/radixdlt/babylon-node) to extract and index data from the network. This document is an API reference documentation, visit [User Guide](https://docs.radixdlt.com/) to learn more about how to run a Gateway of your own. ## Migration guide Please see [the latest release notes](https://github.com/radixdlt/babylon-gateway/releases). ## Integration and forward compatibility guarantees All responses may have additional fields added at any release, so clients are advised to use JSON parsers which ignore unknown fields on JSON objects. When the Radix protocol is updated, new functionality may be added, and so discriminated unions returned by the API may need to be updated to have new variants added, corresponding to the updated data. Clients may need to update in advance to be able to handle these new variants when a protocol update comes out. On the very rare occasions we need to make breaking changes to the API, these will be warned in advance with deprecation notices on previous versions. These deprecation notices will include a safe migration path. Deprecation notes or breaking changes will be flagged clearly in release notes for new versions of the Gateway. The Gateway DB schema is not subject to any compatibility guarantees, and may be changed at any release. DB changes will be flagged in the release notes so clients doing custom DB integrations can prepare. - * - * The version of the OpenAPI document: v1.8.0 - * Generated by: https://github.com/openapitools/openapi-generator.git - */ - - -using System; -using System.Collections; -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Linq; -using System.IO; -using System.Runtime.Serialization; -using System.Text; -using System.Text.RegularExpressions; -using Newtonsoft.Json; -using Newtonsoft.Json.Converters; -using Newtonsoft.Json.Linq; -using FileParameter = RadixDlt.NetworkGateway.GatewayApiSdk.Client.FileParameter; -using OpenAPIDateConverter = RadixDlt.NetworkGateway.GatewayApiSdk.Client.OpenAPIDateConverter; - -namespace RadixDlt.NetworkGateway.GatewayApiSdk.Model -{ - /// - /// TwoWayLinkedEntitiesCollectionAllOf - /// - [DataContract(Name = "TwoWayLinkedEntitiesCollection_allOf")] - public partial class TwoWayLinkedEntitiesCollectionAllOf : IEquatable - { - /// - /// Initializes a new instance of the class. - /// - [JsonConstructorAttribute] - protected TwoWayLinkedEntitiesCollectionAllOf() { } - /// - /// Initializes a new instance of the class. - /// - /// items (required). - public TwoWayLinkedEntitiesCollectionAllOf(List items = default(List)) - { - // to ensure "items" is required (not null) - if (items == null) - { - throw new ArgumentNullException("items is a required property for TwoWayLinkedEntitiesCollectionAllOf and cannot be null"); - } - this.Items = items; - } - - /// - /// Gets or Sets Items - /// - [DataMember(Name = "items", IsRequired = true, EmitDefaultValue = true)] - public List Items { get; set; } - - /// - /// Returns the string presentation of the object - /// - /// String presentation of the object - public override string ToString() - { - StringBuilder sb = new StringBuilder(); - sb.Append("class TwoWayLinkedEntitiesCollectionAllOf {\n"); - sb.Append(" Items: ").Append(Items).Append("\n"); - sb.Append("}\n"); - return sb.ToString(); - } - - /// - /// Returns the JSON string presentation of the object - /// - /// JSON string presentation of the object - public virtual string ToJson() - { - return Newtonsoft.Json.JsonConvert.SerializeObject(this, Newtonsoft.Json.Formatting.Indented); - } - - /// - /// Returns true if objects are equal - /// - /// Object to be compared - /// Boolean - public override bool Equals(object input) - { - return this.Equals(input as TwoWayLinkedEntitiesCollectionAllOf); - } - - /// - /// Returns true if TwoWayLinkedEntitiesCollectionAllOf instances are equal - /// - /// Instance of TwoWayLinkedEntitiesCollectionAllOf to be compared - /// Boolean - public bool Equals(TwoWayLinkedEntitiesCollectionAllOf input) - { - if (input == null) - { - return false; - } - return - ( - this.Items == input.Items || - this.Items != null && - input.Items != null && - this.Items.SequenceEqual(input.Items) - ); - } - - /// - /// Gets the hash code - /// - /// Hash code - public override int GetHashCode() - { - unchecked // Overflow is fine, just wrap - { - int hashCode = 41; - if (this.Items != null) - { - hashCode = (hashCode * 59) + this.Items.GetHashCode(); - } - return hashCode; - } - } - - } - -} diff --git a/src/RadixDlt.NetworkGateway.PostgresIntegration/IoC/GatewayApiBuilderExtensions.cs b/src/RadixDlt.NetworkGateway.PostgresIntegration/IoC/GatewayApiBuilderExtensions.cs index 7d70f6dff..29ca094c3 100644 --- a/src/RadixDlt.NetworkGateway.PostgresIntegration/IoC/GatewayApiBuilderExtensions.cs +++ b/src/RadixDlt.NetworkGateway.PostgresIntegration/IoC/GatewayApiBuilderExtensions.cs @@ -71,6 +71,7 @@ using RadixDlt.NetworkGateway.PostgresIntegration.Interceptors; using RadixDlt.NetworkGateway.PostgresIntegration.Queries; using RadixDlt.NetworkGateway.PostgresIntegration.Services; +using RadixDlt.NetworkGateway.PostgresIntegration.Services.AccountDepositSettings; using RadixDlt.NetworkGateway.PostgresIntegration.Services.PendingTransactions; using IPackageQuerier = RadixDlt.NetworkGateway.GatewayApi.Services.IPackageQuerier; diff --git a/src/RadixDlt.NetworkGateway.PostgresIntegration/LedgerExtension/AccountLockerProcessor.cs b/src/RadixDlt.NetworkGateway.PostgresIntegration/LedgerExtension/AccountLockerProcessor.cs index ca306de1b..7e3c25d14 100644 --- a/src/RadixDlt.NetworkGateway.PostgresIntegration/LedgerExtension/AccountLockerProcessor.cs +++ b/src/RadixDlt.NetworkGateway.PostgresIntegration/LedgerExtension/AccountLockerProcessor.cs @@ -108,14 +108,15 @@ public void VisitUpsert(CoreModel.Substate substateData, ReferencedEntity refere var account = _referencedEntities.Get((EntityAddress)accountLocker.Key.AccountAddress); var keyValueStore = _referencedEntities.Get((EntityAddress)accountLocker.Value.ResourceVaults.EntityAddress); - _definitionsToAdd.Add(new AccountLockerEntryDefinition - { - Id = _context.Sequences.AccountLockerEntryDefinitionSequence++, - FromStateVersion = stateVersion, - AccountLockerEntityId = referencedEntity.DatabaseId, - AccountEntityId = account.DatabaseId, - KeyValueStoreEntityId = keyValueStore.DatabaseId, - }); + _definitionsToAdd.Add( + new AccountLockerEntryDefinition + { + Id = _context.Sequences.AccountLockerEntryDefinitionSequence++, + FromStateVersion = stateVersion, + AccountLockerEntityId = referencedEntity.DatabaseId, + AccountEntityId = account.DatabaseId, + KeyValueStoreEntityId = keyValueStore.DatabaseId, + }); } if (substateData is CoreModel.GenericKeyValueStoreEntrySubstate keyValueStoreEntry) @@ -163,20 +164,24 @@ public async Task LoadDependencies() public void ProcessChanges() { _existingEntryDefinitions.AddRange(_definitionsToAdd.ToDictionary(e => new AccountLockerEntryDbLookup(e.AccountLockerEntityId, e.AccountEntityId))); - _resourceVaultDefinitionsToAdd.AddRange(_observedVaultDefinitions.Select(rv => new AccountLockerEntryResourceVaultDefinition - { - Id = _context.Sequences.AccountLockerEntryResourceVaultDefinitionSequence++, - FromStateVersion = rv.StateVersion, - AccountLockerDefinitionId = _existingEntryDefinitions[new AccountLockerEntryDbLookup(rv.AccountLockerEntityId, rv.AccountEntityId)].Id, - ResourceEntityId = _referencedEntities.Get(rv.ResourceAddress).DatabaseId, - VaultEntityId = _referencedEntities.Get(rv.VaultAddress).DatabaseId, - })); - _touchHistoryToAdd.AddRange(_observedTouchHistory.Select(th => new AccountLockerEntryTouchHistory - { - Id = _context.Sequences.AccountLockerEntryTouchHistorySequence++, - FromStateVersion = th.StateVersion, - AccountLockerDefinitionId = _existingEntryDefinitions[new AccountLockerEntryDbLookup(th.AccountLockerEntityId, th.AccountEntityId)].Id, - })); + _resourceVaultDefinitionsToAdd.AddRange( + _observedVaultDefinitions.Select( + rv => new AccountLockerEntryResourceVaultDefinition + { + Id = _context.Sequences.AccountLockerEntryResourceVaultDefinitionSequence++, + FromStateVersion = rv.StateVersion, + AccountLockerDefinitionId = _existingEntryDefinitions[new AccountLockerEntryDbLookup(rv.AccountLockerEntityId, rv.AccountEntityId)].Id, + ResourceEntityId = _referencedEntities.Get(rv.ResourceAddress).DatabaseId, + VaultEntityId = _referencedEntities.Get(rv.VaultAddress).DatabaseId, + })); + _touchHistoryToAdd.AddRange( + _observedTouchHistory.Select( + th => new AccountLockerEntryTouchHistory + { + Id = _context.Sequences.AccountLockerEntryTouchHistorySequence++, + FromStateVersion = th.StateVersion, + AccountLockerDefinitionId = _existingEntryDefinitions[new AccountLockerEntryDbLookup(th.AccountLockerEntityId, th.AccountEntityId)].Id, + })); } public async Task SaveEntities() diff --git a/src/RadixDlt.NetworkGateway.PostgresIntegration/Queries/KeyValueStoreQueries.cs b/src/RadixDlt.NetworkGateway.PostgresIntegration/Queries/KeyValueStoreQueries.cs index f91769245..51a7726ed 100644 --- a/src/RadixDlt.NetworkGateway.PostgresIntegration/Queries/KeyValueStoreQueries.cs +++ b/src/RadixDlt.NetworkGateway.PostgresIntegration/Queries/KeyValueStoreQueries.cs @@ -1,4 +1,68 @@ -// +/* Copyright 2021 Radix Publishing Ltd incorporated in Jersey (Channel Islands). + * + * Licensed under the Radix License, Version 1.0 (the "License"); you may not use this + * file except in compliance with the License. You may obtain a copy of the License at: + * + * radixfoundation.org/licenses/LICENSE-v1 + * + * The Licensor hereby grants permission for the Canonical version of the Work to be + * published, distributed and used under or by reference to the Licensor’s trademark + * Radix ® and use of any unregistered trade names, logos or get-up. + * + * The Licensor provides the Work (and each Contributor provides its Contributions) on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, + * including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, + * MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. + * + * Whilst the Work is capable of being deployed, used and adopted (instantiated) to create + * a distributed ledger it is your responsibility to test and validate the code, together + * with all logic and performance of that code under all foreseeable scenarios. + * + * The Licensor does not make or purport to make and hereby excludes liability for all + * and any representation, warranty or undertaking in any form whatsoever, whether express + * or implied, to any entity or person, including any representation, warranty or + * undertaking, as to the functionality security use, value or other characteristics of + * any distributed ledger nor in respect the functioning or value of any tokens which may + * be created stored or transferred using the Work. The Licensor does not warrant that the + * Work or any use of the Work complies with any law or regulation in any territory where + * it may be implemented or used or that it will be appropriate for any specific purpose. + * + * Neither the licensor nor any current or former employees, officers, directors, partners, + * trustees, representatives, agents, advisors, contractors, or volunteers of the Licensor + * shall be liable for any direct or indirect, special, incidental, consequential or other + * losses of any kind, in tort, contract or otherwise (including but not limited to loss + * of revenue, income or profits, or loss of use or data, or loss of reputation, or loss + * of any economic or other opportunity of whatsoever nature or howsoever arising), arising + * out of or in connection with (without limitation of any use, misuse, of any ledger system + * or use made or its functionality or any performance or operation of any code or protocol + * caused by bugs or programming or logic errors or otherwise); + * + * A. any offer, purchase, holding, use, sale, exchange or transmission of any + * cryptographic keys, tokens or assets created, exchanged, stored or arising from any + * interaction with the Work; + * + * B. any failure in a transmission or loss of any token or assets keys or other digital + * artefacts due to errors in transmission; + * + * C. bugs, hacks, logic errors or faults in the Work or any communication; + * + * D. system software or apparatus including but not limited to losses caused by errors + * in holding or transmitting tokens by any third-party; + * + * E. breaches or failure of security including hacker attacks, loss or disclosure of + * password, loss of private key, unauthorised use or misuse of such passwords or keys; + * + * F. any losses including loss of anticipated savings or other benefits resulting from + * use of the Work or any changes to the Work (however implemented). + * + * You are solely responsible for; testing, validating and evaluation of all operation + * logic, functionality, security and appropriateness of using the Work for any commercial + * or non-commercial purpose and for any reproduction or redistribution by You of the + * Work. You assume all risks associated with Your use of the Work and the exercise of + * permissions under this License. + */ + +// // Copyright (c) PlaceholderCompany. All rights reserved. // diff --git a/src/RadixDlt.NetworkGateway.PostgresIntegration/Services/AccountDepositSettings/DepositPreValidationQuerier.cs b/src/RadixDlt.NetworkGateway.PostgresIntegration/Services/AccountDepositSettings/DepositPreValidationQuerier.cs index dd29738f3..92edb72b2 100644 --- a/src/RadixDlt.NetworkGateway.PostgresIntegration/Services/AccountDepositSettings/DepositPreValidationQuerier.cs +++ b/src/RadixDlt.NetworkGateway.PostgresIntegration/Services/AccountDepositSettings/DepositPreValidationQuerier.cs @@ -76,14 +76,14 @@ using System.Threading.Tasks; using GatewayModel = RadixDlt.NetworkGateway.GatewayApiSdk.Model; -namespace RadixDlt.NetworkGateway.PostgresIntegration.Services; - -internal record DepositPreValidationResourcePreferenceRulesViewModel( - long ResourceEntityId, - AccountResourcePreferenceRule AccountResourcePreferenceRule); +namespace RadixDlt.NetworkGateway.PostgresIntegration.Services.AccountDepositSettings; internal class DepositPreValidationQuerier : IDepositPreValidationQuerier { + private record DepositPreValidationResourcePreferenceRulesViewModel( + long ResourceEntityId, + AccountResourcePreferenceRule AccountResourcePreferenceRule); + private readonly IDapperWrapper _dapperWrapper; private readonly ReadOnlyDbContext _dbContext; private readonly INetworkConfigurationProvider _networkConfigurationProvider; diff --git a/src/RadixDlt.NetworkGateway.PostgresIntegration/Services/AccountLockerQuerier.cs b/src/RadixDlt.NetworkGateway.PostgresIntegration/Services/AccountLockerQuerier.cs index a605b0b29..0169a6b36 100644 --- a/src/RadixDlt.NetworkGateway.PostgresIntegration/Services/AccountLockerQuerier.cs +++ b/src/RadixDlt.NetworkGateway.PostgresIntegration/Services/AccountLockerQuerier.cs @@ -118,7 +118,14 @@ public AccountLockerQuerier(IEntityQuerier entityQuerier, ReadOnlyDbContext read var cd = new CommandDefinition( commandText: @" -SELECT d.id AS Id, d.from_state_version AS FromStateVersion, re.discriminator AS ResourceDiscriminator, re.address AS ResourceAddress, ve.address AS VaultAddress, vh.from_state_version AS LastUpdatedAtStateVersion, vh.balance AS Balance +SELECT + d.id AS Id, + d.from_state_version AS FromStateVersion, + re.discriminator AS ResourceDiscriminator, + re.address AS ResourceAddress, + ve.address AS VaultAddress, + vh.from_state_version AS LastUpdatedAtStateVersion, + vh.balance AS Balance FROM account_locker_entry_resource_vault_definition d INNER JOIN entities re ON re.id = d.resource_entity_id INNER JOIN entities ve ON ve.id = d.vault_entity_id diff --git a/src/RadixDlt.NetworkGateway.PostgresIntegration/Services/ValidatorQuerier.cs b/src/RadixDlt.NetworkGateway.PostgresIntegration/Services/ValidatorQuerier.cs index 71783ee89..07b219258 100644 --- a/src/RadixDlt.NetworkGateway.PostgresIntegration/Services/ValidatorQuerier.cs +++ b/src/RadixDlt.NetworkGateway.PostgresIntegration/Services/ValidatorQuerier.cs @@ -179,6 +179,14 @@ LIMIT 1 var validatorsPageSize = _endpointConfiguration.Value.ValidatorsPageSize; var idBoundary = cursor?.IdBoundary ?? 0; + var validatorsCount = await _dbContext + .Entities + .OfType() + .Where(e => e.FromStateVersion <= ledgerState.StateVersion) + .Where(e => e.Id >= idBoundary) + .AnnotateMetricName("GetValidatorsCount") + .CountAsync(token); + var validatorsAndOneMore = await _dbContext .Entities .OfType() @@ -335,6 +343,6 @@ LIMIT 1 ? new GatewayModel.StateValidatorsListCursor(validatorsAndOneMore.Last().Id).ToCursorString() : null; - return new GatewayModel.StateValidatorsListResponse(ledgerState, new GatewayModel.ValidatorCollection(null, nextCursor, items)); + return new GatewayModel.StateValidatorsListResponse(ledgerState, new GatewayModel.ValidatorCollection(validatorsCount, nextCursor, items)); } } From adb322a98dddd604d69917d2980fef1359ace81f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Pawelec?= Date: Wed, 2 Oct 2024 13:15:53 +0200 Subject: [PATCH 3/3] cleanup. --- CHANGELOG.md | 2 +- .../Services/IResourceHoldersQuerier.cs | 4 --- ...uthorizedDepositorsPageRequestValidator.cs | 4 --- ...ResourcePreferencesPageRequestValidator.cs | 4 --- ...ctionTransferValidationRequestValidator.cs | 4 --- ...eAccountAuthorizedDepositorsPageRequest.cs | 4 --- ...teAccountResourcePreferencesPageRequest.cs | 4 --- .../AffectedGlobalEntitiesProcessor.cs | 4 --- .../KeyValueStoreTotalsHistory.cs | 4 --- .../Queries/KeyValueStoreQueries.cs | 33 ++++++++----------- .../Queries/MetadataPagedQuery.cs | 5 +-- .../AccountStateQuerier.cs | 4 --- .../Services/KeyValueStoreQuerier.cs | 6 ++-- 13 files changed, 18 insertions(+), 64 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f3aadab3e..a420ec2a2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,8 +29,8 @@ Release built: _not released yet_ ### Bug fixes - - Added missing `total_count` property to `/state/validators/list` response. + ### API Changes - Restored previously removed `total_count` property to `/state/key-value-store/keys` endpoint. diff --git a/src/RadixDlt.NetworkGateway.GatewayApi/Services/IResourceHoldersQuerier.cs b/src/RadixDlt.NetworkGateway.GatewayApi/Services/IResourceHoldersQuerier.cs index d3bea5d4d..52ca9bf80 100644 --- a/src/RadixDlt.NetworkGateway.GatewayApi/Services/IResourceHoldersQuerier.cs +++ b/src/RadixDlt.NetworkGateway.GatewayApi/Services/IResourceHoldersQuerier.cs @@ -62,10 +62,6 @@ * permissions under this License. */ -// -// Copyright (c) PlaceholderCompany. All rights reserved. -// - using RadixDlt.NetworkGateway.Abstractions; using System.Threading; using System.Threading.Tasks; diff --git a/src/RadixDlt.NetworkGateway.GatewayApi/Validators/StateAccountAuthorizedDepositorsPageRequestValidator.cs b/src/RadixDlt.NetworkGateway.GatewayApi/Validators/StateAccountAuthorizedDepositorsPageRequestValidator.cs index 99f9e9271..cc10debf3 100644 --- a/src/RadixDlt.NetworkGateway.GatewayApi/Validators/StateAccountAuthorizedDepositorsPageRequestValidator.cs +++ b/src/RadixDlt.NetworkGateway.GatewayApi/Validators/StateAccountAuthorizedDepositorsPageRequestValidator.cs @@ -62,10 +62,6 @@ * permissions under this License. */ -// -// Copyright (c) PlaceholderCompany. All rights reserved. -// - using FluentValidation; using RadixDlt.NetworkGateway.GatewayApiSdk.Model; diff --git a/src/RadixDlt.NetworkGateway.GatewayApi/Validators/StateAccountResourcePreferencesPageRequestValidator.cs b/src/RadixDlt.NetworkGateway.GatewayApi/Validators/StateAccountResourcePreferencesPageRequestValidator.cs index faba52623..ec769292a 100644 --- a/src/RadixDlt.NetworkGateway.GatewayApi/Validators/StateAccountResourcePreferencesPageRequestValidator.cs +++ b/src/RadixDlt.NetworkGateway.GatewayApi/Validators/StateAccountResourcePreferencesPageRequestValidator.cs @@ -62,10 +62,6 @@ * permissions under this License. */ -// -// Copyright (c) PlaceholderCompany. All rights reserved. -// - using FluentValidation; using RadixDlt.NetworkGateway.GatewayApiSdk.Model; diff --git a/src/RadixDlt.NetworkGateway.GatewayApi/Validators/TransactionTransferValidationRequestValidator.cs b/src/RadixDlt.NetworkGateway.GatewayApi/Validators/TransactionTransferValidationRequestValidator.cs index d99f4d803..c1448ae9a 100644 --- a/src/RadixDlt.NetworkGateway.GatewayApi/Validators/TransactionTransferValidationRequestValidator.cs +++ b/src/RadixDlt.NetworkGateway.GatewayApi/Validators/TransactionTransferValidationRequestValidator.cs @@ -62,10 +62,6 @@ * permissions under this License. */ -// -// Copyright (c) PlaceholderCompany. All rights reserved. -// - using FluentValidation; using Microsoft.Extensions.Options; using RadixDlt.NetworkGateway.GatewayApi.Configuration; diff --git a/src/RadixDlt.NetworkGateway.GatewayApiSdk/Model/StateAccountAuthorizedDepositorsPageRequest.cs b/src/RadixDlt.NetworkGateway.GatewayApiSdk/Model/StateAccountAuthorizedDepositorsPageRequest.cs index ee330e4d9..dbf3a5972 100644 --- a/src/RadixDlt.NetworkGateway.GatewayApiSdk/Model/StateAccountAuthorizedDepositorsPageRequest.cs +++ b/src/RadixDlt.NetworkGateway.GatewayApiSdk/Model/StateAccountAuthorizedDepositorsPageRequest.cs @@ -62,10 +62,6 @@ * permissions under this License. */ -// -// Copyright (c) PlaceholderCompany. All rights reserved. -// - namespace RadixDlt.NetworkGateway.GatewayApiSdk.Model; public partial class StateAccountAuthorizedDepositorsPageRequest : IPaginableRequest diff --git a/src/RadixDlt.NetworkGateway.GatewayApiSdk/Model/StateAccountResourcePreferencesPageRequest.cs b/src/RadixDlt.NetworkGateway.GatewayApiSdk/Model/StateAccountResourcePreferencesPageRequest.cs index 3ab22972a..b50c49a0e 100644 --- a/src/RadixDlt.NetworkGateway.GatewayApiSdk/Model/StateAccountResourcePreferencesPageRequest.cs +++ b/src/RadixDlt.NetworkGateway.GatewayApiSdk/Model/StateAccountResourcePreferencesPageRequest.cs @@ -62,10 +62,6 @@ * permissions under this License. */ -// -// Copyright (c) PlaceholderCompany. All rights reserved. -// - namespace RadixDlt.NetworkGateway.GatewayApiSdk.Model; public partial class StateAccountResourcePreferencesPageRequest : IPaginableRequest diff --git a/src/RadixDlt.NetworkGateway.PostgresIntegration/LedgerExtension/AffectedGlobalEntitiesProcessor.cs b/src/RadixDlt.NetworkGateway.PostgresIntegration/LedgerExtension/AffectedGlobalEntitiesProcessor.cs index da223a040..14a1c1d3c 100644 --- a/src/RadixDlt.NetworkGateway.PostgresIntegration/LedgerExtension/AffectedGlobalEntitiesProcessor.cs +++ b/src/RadixDlt.NetworkGateway.PostgresIntegration/LedgerExtension/AffectedGlobalEntitiesProcessor.cs @@ -62,10 +62,6 @@ * permissions under this License. */ -// -// Copyright (c) PlaceholderCompany. All rights reserved. -// - using RadixDlt.NetworkGateway.Abstractions; using RadixDlt.NetworkGateway.Abstractions.Network; using RadixDlt.NetworkGateway.PostgresIntegration.Models; diff --git a/src/RadixDlt.NetworkGateway.PostgresIntegration/Models/KeyValueStore/KeyValueStoreTotalsHistory.cs b/src/RadixDlt.NetworkGateway.PostgresIntegration/Models/KeyValueStore/KeyValueStoreTotalsHistory.cs index 433948926..491b3b70c 100644 --- a/src/RadixDlt.NetworkGateway.PostgresIntegration/Models/KeyValueStore/KeyValueStoreTotalsHistory.cs +++ b/src/RadixDlt.NetworkGateway.PostgresIntegration/Models/KeyValueStore/KeyValueStoreTotalsHistory.cs @@ -62,10 +62,6 @@ * permissions under this License. */ -// -// Copyright (c) PlaceholderCompany. All rights reserved. -// - using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; diff --git a/src/RadixDlt.NetworkGateway.PostgresIntegration/Queries/KeyValueStoreQueries.cs b/src/RadixDlt.NetworkGateway.PostgresIntegration/Queries/KeyValueStoreQueries.cs index 51a7726ed..45238077e 100644 --- a/src/RadixDlt.NetworkGateway.PostgresIntegration/Queries/KeyValueStoreQueries.cs +++ b/src/RadixDlt.NetworkGateway.PostgresIntegration/Queries/KeyValueStoreQueries.cs @@ -62,10 +62,6 @@ * permissions under this License. */ -// -// Copyright (c) PlaceholderCompany. All rights reserved. -// - using Dapper; using Microsoft.EntityFrameworkCore; using RadixDlt.NetworkGateway.Abstractions; @@ -200,10 +196,7 @@ LEFT JOIN LATERAL ( entries.value, entries.is_locked, entries.is_deleted, - CASE WHEN (ROW_NUMBER() OVER (ORDER BY definitions.cursor DESC)) = vars.page_limit OR entries.filter_out - THEN TRUE - ELSE FALSE - END AS filter_out, + ROW_NUMBER() OVER (ORDER BY definitions.cursor DESC) = vars.page_limit OR entries.filter_out AS filter_out, CASE WHEN (ROW_NUMBER() OVER (ORDER BY definitions.cursor DESC)) = vars.page_limit THEN definitions.cursor @@ -211,16 +204,16 @@ THEN definitions.cursor THEN ROW(definitions.key_first_seen_state_version, definitions.id - 1) END AS next_cursor_inclusive FROM ( - SELECT - d.id, - d.key, - d.cursor, - d.from_state_version AS key_first_seen_state_version, - (ROW_NUMBER() OVER (ORDER BY d.cursor DESC)) = vars.definition_read_limit AS is_last_candidate - FROM definitions_with_cursor d - WHERE d.key_value_store_entity_id = vars.key_value_store_entity_id AND ((NOT vars.use_cursor) OR d.cursor <= vars.start_cursor_inclusive) - ORDER BY d.cursor DESC - LIMIT vars.definition_read_limit + SELECT + d.id, + d.key, + d.cursor, + d.from_state_version AS key_first_seen_state_version, + (ROW_NUMBER() OVER (ORDER BY d.cursor DESC)) = vars.definition_read_limit AS is_last_candidate + FROM definitions_with_cursor d + WHERE d.key_value_store_entity_id = vars.key_value_store_entity_id AND ((NOT vars.use_cursor) OR d.cursor <= vars.start_cursor_inclusive) + ORDER BY d.cursor DESC + LIMIT vars.definition_read_limit ) definitions INNER JOIN LATERAL ( SELECT @@ -292,7 +285,7 @@ ORDER BY entries_per_entity.cursor DESC ); } - internal static async Task KeyValueStoreData( + internal static async Task KeyValueStoreDataMultiLookupQuery( ReadOnlyDbContext dbContext, IDapperWrapper dapperWrapper, Entity keyValueStoreEntity, @@ -385,7 +378,7 @@ LIMIT 1 return new GatewayModel.StateKeyValueStoreDataResponse(ledgerState, keyValueStoreEntity.Address, items); } - internal static async Task KeyValueStoreSchema( + internal static async Task KeyValueStoreSchemaLookupQuery( ReadOnlyDbContext dbContext, IDapperWrapper dapperWrapper, long keyValueStoreId, diff --git a/src/RadixDlt.NetworkGateway.PostgresIntegration/Queries/MetadataPagedQuery.cs b/src/RadixDlt.NetworkGateway.PostgresIntegration/Queries/MetadataPagedQuery.cs index bbe6ba040..c47992725 100644 --- a/src/RadixDlt.NetworkGateway.PostgresIntegration/Queries/MetadataPagedQuery.cs +++ b/src/RadixDlt.NetworkGateway.PostgresIntegration/Queries/MetadataPagedQuery.cs @@ -181,10 +181,7 @@ LEFT JOIN LATERAL ( entries.value, entries.is_locked, entries.is_deleted, - CASE WHEN (ROW_NUMBER() OVER (ORDER BY definitions.cursor DESC)) = vars.per_entity_page_limit OR entries.filter_out - THEN TRUE - ELSE FALSE - END AS filter_out, + ROW_NUMBER() OVER (ORDER BY definitions.cursor DESC) = vars.per_entity_page_limit OR entries.filter_out AS filter_out, CASE WHEN (ROW_NUMBER() OVER (ORDER BY definitions.cursor DESC)) = vars.per_entity_page_limit THEN definitions.cursor diff --git a/src/RadixDlt.NetworkGateway.PostgresIntegration/Services/AccountDepositSettings/AccountStateQuerier.cs b/src/RadixDlt.NetworkGateway.PostgresIntegration/Services/AccountDepositSettings/AccountStateQuerier.cs index af3771949..a938a73fb 100644 --- a/src/RadixDlt.NetworkGateway.PostgresIntegration/Services/AccountDepositSettings/AccountStateQuerier.cs +++ b/src/RadixDlt.NetworkGateway.PostgresIntegration/Services/AccountDepositSettings/AccountStateQuerier.cs @@ -62,10 +62,6 @@ * permissions under this License. */ -// -// Copyright (c) PlaceholderCompany. All rights reserved. -// - using Dapper; using Microsoft.EntityFrameworkCore; using RadixDlt.NetworkGateway.Abstractions; diff --git a/src/RadixDlt.NetworkGateway.PostgresIntegration/Services/KeyValueStoreQuerier.cs b/src/RadixDlt.NetworkGateway.PostgresIntegration/Services/KeyValueStoreQuerier.cs index c947bea60..13bad5903 100644 --- a/src/RadixDlt.NetworkGateway.PostgresIntegration/Services/KeyValueStoreQuerier.cs +++ b/src/RadixDlt.NetworkGateway.PostgresIntegration/Services/KeyValueStoreQuerier.cs @@ -108,7 +108,7 @@ public KeyValueStoreQuerier( var networkId = (await _networkConfigurationProvider.GetNetworkConfiguration(token)).Id; var keyValueStore = await _entityQuerier.GetNonVirtualEntity(_dbContext, keyValueStoreAddress, ledgerState, token); - var keyValueStoreSchema = await KeyValueStoreQueries.KeyValueStoreSchema( + var keyValueStoreSchema = await KeyValueStoreQueries.KeyValueStoreSchemaLookupQuery( _dbContext, _dapperWrapper, keyValueStore.Id, @@ -140,14 +140,14 @@ public KeyValueStoreQuerier( var networkId = (await _networkConfigurationProvider.GetNetworkConfiguration(token)).Id; var keyValueStore = await _entityQuerier.GetNonVirtualEntity(_dbContext, keyValueStoreAddress, ledgerState, token); - var keyValueStoreSchema = await KeyValueStoreQueries.KeyValueStoreSchema( + var keyValueStoreSchema = await KeyValueStoreQueries.KeyValueStoreSchemaLookupQuery( _dbContext, _dapperWrapper, keyValueStore.Id, ledgerState, token); - return await KeyValueStoreQueries.KeyValueStoreData( + return await KeyValueStoreQueries.KeyValueStoreDataMultiLookupQuery( _dbContext, _dapperWrapper, keyValueStore,