using Microsoft.EntityFrameworkCore.Migrations; #nullable disable namespace ZB.MOM.WW.OtOpcUa.Configuration.Migrations { /// /// Extends dbo.sp_ComputeGenerationDiff to emit NodeAcl rows alongside the /// existing Namespace/DriverInstance/Equipment/Tag output — closes the final slice of /// task #196 (DiffViewer ACL section). Logical id for NodeAcl is a composite /// LdapGroup|ScopeKind|ScopeId triple so a Change row surfaces whether the grant /// shifted permissions, moved scope, or was added/removed outright. /// /// public partial class ExtendComputeGenerationDiffWithNodeAcl : Migration { /// protected override void Up(MigrationBuilder migrationBuilder) { migrationBuilder.Sql(Procs.ComputeGenerationDiffV2); } /// protected override void Down(MigrationBuilder migrationBuilder) { migrationBuilder.Sql(Procs.ComputeGenerationDiffV1); } private static class Procs { /// V2 — adds the NodeAcl section to the diff output. public const string ComputeGenerationDiffV2 = @" CREATE OR ALTER PROCEDURE dbo.sp_ComputeGenerationDiff @FromGenerationId bigint, @ToGenerationId bigint AS BEGIN SET NOCOUNT ON; CREATE TABLE #diff (TableName nvarchar(32), LogicalId nvarchar(128), ChangeKind nvarchar(16)); WITH f AS (SELECT NamespaceId AS LogicalId, CHECKSUM(NamespaceUri, Kind, Enabled, Notes) AS Sig FROM dbo.Namespace WHERE GenerationId = @FromGenerationId), t AS (SELECT NamespaceId AS LogicalId, CHECKSUM(NamespaceUri, Kind, Enabled, Notes) AS Sig FROM dbo.Namespace WHERE GenerationId = @ToGenerationId) INSERT #diff SELECT 'Namespace', CONVERT(nvarchar(128), COALESCE(f.LogicalId, t.LogicalId)), CASE WHEN f.LogicalId IS NULL THEN 'Added' WHEN t.LogicalId IS NULL THEN 'Removed' WHEN f.Sig <> t.Sig THEN 'Modified' ELSE 'Unchanged' END FROM f FULL OUTER JOIN t ON f.LogicalId = t.LogicalId WHERE f.LogicalId IS NULL OR t.LogicalId IS NULL OR f.Sig <> t.Sig; WITH f AS (SELECT DriverInstanceId AS LogicalId, CHECKSUM(ClusterId, NamespaceId, Name, DriverType, Enabled, CONVERT(varchar(max), DriverConfig)) AS Sig FROM dbo.DriverInstance WHERE GenerationId = @FromGenerationId), t AS (SELECT DriverInstanceId AS LogicalId, CHECKSUM(ClusterId, NamespaceId, Name, DriverType, Enabled, CONVERT(varchar(max), DriverConfig)) AS Sig FROM dbo.DriverInstance WHERE GenerationId = @ToGenerationId) INSERT #diff SELECT 'DriverInstance', CONVERT(nvarchar(128), COALESCE(f.LogicalId, t.LogicalId)), CASE WHEN f.LogicalId IS NULL THEN 'Added' WHEN t.LogicalId IS NULL THEN 'Removed' WHEN f.Sig <> t.Sig THEN 'Modified' ELSE 'Unchanged' END FROM f FULL OUTER JOIN t ON f.LogicalId = t.LogicalId WHERE f.LogicalId IS NULL OR t.LogicalId IS NULL OR f.Sig <> t.Sig; WITH f AS (SELECT EquipmentId AS LogicalId, CHECKSUM(EquipmentUuid, DriverInstanceId, UnsLineId, Name, MachineCode, ZTag, SAPID, EquipmentClassRef, Manufacturer, Model, SerialNumber) AS Sig FROM dbo.Equipment WHERE GenerationId = @FromGenerationId), t AS (SELECT EquipmentId AS LogicalId, CHECKSUM(EquipmentUuid, DriverInstanceId, UnsLineId, Name, MachineCode, ZTag, SAPID, EquipmentClassRef, Manufacturer, Model, SerialNumber) AS Sig FROM dbo.Equipment WHERE GenerationId = @ToGenerationId) INSERT #diff SELECT 'Equipment', CONVERT(nvarchar(128), COALESCE(f.LogicalId, t.LogicalId)), CASE WHEN f.LogicalId IS NULL THEN 'Added' WHEN t.LogicalId IS NULL THEN 'Removed' WHEN f.Sig <> t.Sig THEN 'Modified' ELSE 'Unchanged' END FROM f FULL OUTER JOIN t ON f.LogicalId = t.LogicalId WHERE f.LogicalId IS NULL OR t.LogicalId IS NULL OR f.Sig <> t.Sig; WITH f AS (SELECT TagId AS LogicalId, CHECKSUM(DriverInstanceId, DeviceId, EquipmentId, PollGroupId, FolderPath, Name, DataType, AccessLevel, WriteIdempotent, CONVERT(varchar(max), TagConfig)) AS Sig FROM dbo.Tag WHERE GenerationId = @FromGenerationId), t AS (SELECT TagId AS LogicalId, CHECKSUM(DriverInstanceId, DeviceId, EquipmentId, PollGroupId, FolderPath, Name, DataType, AccessLevel, WriteIdempotent, CONVERT(varchar(max), TagConfig)) AS Sig FROM dbo.Tag WHERE GenerationId = @ToGenerationId) INSERT #diff SELECT 'Tag', CONVERT(nvarchar(128), COALESCE(f.LogicalId, t.LogicalId)), CASE WHEN f.LogicalId IS NULL THEN 'Added' WHEN t.LogicalId IS NULL THEN 'Removed' WHEN f.Sig <> t.Sig THEN 'Modified' ELSE 'Unchanged' END FROM f FULL OUTER JOIN t ON f.LogicalId = t.LogicalId WHERE f.LogicalId IS NULL OR t.LogicalId IS NULL OR f.Sig <> t.Sig; -- NodeAcl section. Logical id is the (LdapGroup, ScopeKind, ScopeId) triple so the diff -- distinguishes same row with new permissions (Modified via CHECKSUM on PermissionFlags + Notes) -- from a scope move (which surfaces as Added + Removed of different logical ids). WITH f AS ( SELECT CONVERT(nvarchar(128), LdapGroup + '|' + CONVERT(nvarchar(16), ScopeKind) + '|' + ISNULL(ScopeId, '(cluster)')) AS LogicalId, CHECKSUM(ClusterId, PermissionFlags, Notes) AS Sig FROM dbo.NodeAcl WHERE GenerationId = @FromGenerationId), t AS ( SELECT CONVERT(nvarchar(128), LdapGroup + '|' + CONVERT(nvarchar(16), ScopeKind) + '|' + ISNULL(ScopeId, '(cluster)')) AS LogicalId, CHECKSUM(ClusterId, PermissionFlags, Notes) AS Sig FROM dbo.NodeAcl WHERE GenerationId = @ToGenerationId) INSERT #diff SELECT 'NodeAcl', COALESCE(f.LogicalId, t.LogicalId), CASE WHEN f.LogicalId IS NULL THEN 'Added' WHEN t.LogicalId IS NULL THEN 'Removed' WHEN f.Sig <> t.Sig THEN 'Modified' ELSE 'Unchanged' END FROM f FULL OUTER JOIN t ON f.LogicalId = t.LogicalId WHERE f.LogicalId IS NULL OR t.LogicalId IS NULL OR f.Sig <> t.Sig; SELECT TableName, LogicalId, ChangeKind FROM #diff; DROP TABLE #diff; END "; /// V1 — exact proc shipped in migration 20260417215224_StoredProcedures. Restored on Down(). public const string ComputeGenerationDiffV1 = @" CREATE OR ALTER PROCEDURE dbo.sp_ComputeGenerationDiff @FromGenerationId bigint, @ToGenerationId bigint AS BEGIN SET NOCOUNT ON; CREATE TABLE #diff (TableName nvarchar(32), LogicalId nvarchar(64), ChangeKind nvarchar(16)); WITH f AS (SELECT NamespaceId AS LogicalId, CHECKSUM(NamespaceUri, Kind, Enabled, Notes) AS Sig FROM dbo.Namespace WHERE GenerationId = @FromGenerationId), t AS (SELECT NamespaceId AS LogicalId, CHECKSUM(NamespaceUri, Kind, Enabled, Notes) AS Sig FROM dbo.Namespace WHERE GenerationId = @ToGenerationId) INSERT #diff SELECT 'Namespace', CONVERT(nvarchar(64), COALESCE(f.LogicalId, t.LogicalId)), CASE WHEN f.LogicalId IS NULL THEN 'Added' WHEN t.LogicalId IS NULL THEN 'Removed' WHEN f.Sig <> t.Sig THEN 'Modified' ELSE 'Unchanged' END FROM f FULL OUTER JOIN t ON f.LogicalId = t.LogicalId WHERE f.LogicalId IS NULL OR t.LogicalId IS NULL OR f.Sig <> t.Sig; WITH f AS (SELECT DriverInstanceId AS LogicalId, CHECKSUM(ClusterId, NamespaceId, Name, DriverType, Enabled, CONVERT(varchar(max), DriverConfig)) AS Sig FROM dbo.DriverInstance WHERE GenerationId = @FromGenerationId), t AS (SELECT DriverInstanceId AS LogicalId, CHECKSUM(ClusterId, NamespaceId, Name, DriverType, Enabled, CONVERT(varchar(max), DriverConfig)) AS Sig FROM dbo.DriverInstance WHERE GenerationId = @ToGenerationId) INSERT #diff SELECT 'DriverInstance', CONVERT(nvarchar(64), COALESCE(f.LogicalId, t.LogicalId)), CASE WHEN f.LogicalId IS NULL THEN 'Added' WHEN t.LogicalId IS NULL THEN 'Removed' WHEN f.Sig <> t.Sig THEN 'Modified' ELSE 'Unchanged' END FROM f FULL OUTER JOIN t ON f.LogicalId = t.LogicalId WHERE f.LogicalId IS NULL OR t.LogicalId IS NULL OR f.Sig <> t.Sig; WITH f AS (SELECT EquipmentId AS LogicalId, CHECKSUM(EquipmentUuid, DriverInstanceId, UnsLineId, Name, MachineCode, ZTag, SAPID, EquipmentClassRef, Manufacturer, Model, SerialNumber) AS Sig FROM dbo.Equipment WHERE GenerationId = @FromGenerationId), t AS (SELECT EquipmentId AS LogicalId, CHECKSUM(EquipmentUuid, DriverInstanceId, UnsLineId, Name, MachineCode, ZTag, SAPID, EquipmentClassRef, Manufacturer, Model, SerialNumber) AS Sig FROM dbo.Equipment WHERE GenerationId = @ToGenerationId) INSERT #diff SELECT 'Equipment', CONVERT(nvarchar(64), COALESCE(f.LogicalId, t.LogicalId)), CASE WHEN f.LogicalId IS NULL THEN 'Added' WHEN t.LogicalId IS NULL THEN 'Removed' WHEN f.Sig <> t.Sig THEN 'Modified' ELSE 'Unchanged' END FROM f FULL OUTER JOIN t ON f.LogicalId = t.LogicalId WHERE f.LogicalId IS NULL OR t.LogicalId IS NULL OR f.Sig <> t.Sig; WITH f AS (SELECT TagId AS LogicalId, CHECKSUM(DriverInstanceId, DeviceId, EquipmentId, PollGroupId, FolderPath, Name, DataType, AccessLevel, WriteIdempotent, CONVERT(varchar(max), TagConfig)) AS Sig FROM dbo.Tag WHERE GenerationId = @FromGenerationId), t AS (SELECT TagId AS LogicalId, CHECKSUM(DriverInstanceId, DeviceId, EquipmentId, PollGroupId, FolderPath, Name, DataType, AccessLevel, WriteIdempotent, CONVERT(varchar(max), TagConfig)) AS Sig FROM dbo.Tag WHERE GenerationId = @ToGenerationId) INSERT #diff SELECT 'Tag', CONVERT(nvarchar(64), COALESCE(f.LogicalId, t.LogicalId)), CASE WHEN f.LogicalId IS NULL THEN 'Added' WHEN t.LogicalId IS NULL THEN 'Removed' WHEN f.Sig <> t.Sig THEN 'Modified' ELSE 'Unchanged' END FROM f FULL OUTER JOIN t ON f.LogicalId = t.LogicalId WHERE f.LogicalId IS NULL OR t.LogicalId IS NULL OR f.Sig <> t.Sig; SELECT TableName, LogicalId, ChangeKind FROM #diff; DROP TABLE #diff; END "; } } }