fix(config): also clean NodeAcl + release ExternalIdReservation in SystemPlatform cleanup migration
This commit is contained in:
+61
@@ -29,6 +29,15 @@ namespace ZB.MOM.WW.OtOpcUa.Configuration.Migrations
|
||||
/// is keyed off the set of SystemPlatform namespaces, so on a DB with zero such rows every
|
||||
/// DELETE simply affects 0 rows (idempotent / safe to run repeatedly).
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// Two tables carry LOGICAL refs with no physical FK and so were easy to miss: <c>NodeAcl</c>
|
||||
/// (per-scope grants keyed by <c>ScopeKind</c> + <c>ScopeId</c>) is cleaned for the
|
||||
/// Namespace/Equipment/FolderSegment/Tag scopes that get deleted, and
|
||||
/// <c>ExternalIdReservation</c> (fleet-wide ZTag/SAPID reservations keyed by
|
||||
/// <c>EquipmentUuid</c>) is RELEASED — not deleted — for the affected equipment so the
|
||||
/// reserved external IDs free up while the audit row survives. Both run before the entity
|
||||
/// rows they reference are removed so the id subqueries still resolve.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
/// <inheritdoc />
|
||||
public partial class CleanupSystemPlatformNamespaces : Migration
|
||||
@@ -44,6 +53,58 @@ namespace ZB.MOM.WW.OtOpcUa.Configuration.Migrations
|
||||
-- stray equipment-scoped tag / Equipment could be bound to a SystemPlatform-namespace driver. Clean
|
||||
-- both, plus anything that FKs into the affected Equipment (VirtualTag / ScriptedAlarm / state).
|
||||
|
||||
-- Logical-reference cleanup that must run FIRST -------------------------------------------
|
||||
-- NodeAcl rows carry purely LOGICAL scope refs (ScopeKind + ScopeId, no physical FK). When the
|
||||
-- scoped entity is deleted below the ScopeId dangles and the ACL evaluator would still match it,
|
||||
-- silently granting/denying on a node that no longer exists. ScopeKind persists as a string via
|
||||
-- HasConversion<string>, so the values below ('Namespace'/'Equipment'/'FolderSegment'/'Tag') are
|
||||
-- the literal enum member names. These deletes must read the entity-id subqueries while those rows
|
||||
-- still exist, hence they run before the entity DELETEs further down.
|
||||
|
||||
-- Namespace-scoped grants pointing at the SystemPlatform namespaces themselves.
|
||||
DELETE FROM [NodeAcl]
|
||||
WHERE [ScopeKind] = 'Namespace'
|
||||
AND [ScopeId] IN (
|
||||
SELECT [NamespaceId] FROM [Namespace] WHERE [Kind] = 'SystemPlatform');
|
||||
|
||||
-- Equipment- and FolderSegment-scoped grants pointing at Equipment that hangs off the affected
|
||||
-- DriverInstances (both share Equipment.EquipmentId as the ScopeId).
|
||||
DELETE FROM [NodeAcl]
|
||||
WHERE [ScopeKind] IN ('Equipment', 'FolderSegment')
|
||||
AND [ScopeId] IN (
|
||||
SELECT [EquipmentId] FROM [Equipment]
|
||||
WHERE [DriverInstanceId] IN (
|
||||
SELECT [DriverInstanceId] FROM [DriverInstance]
|
||||
WHERE [NamespaceId] IN (
|
||||
SELECT [NamespaceId] FROM [Namespace] WHERE [Kind] = 'SystemPlatform')));
|
||||
|
||||
-- Tag-scoped grants pointing at Tags bound to the affected DriverInstances (ScopeId = Tag.TagId).
|
||||
DELETE FROM [NodeAcl]
|
||||
WHERE [ScopeKind] = 'Tag'
|
||||
AND [ScopeId] IN (
|
||||
SELECT [TagId] FROM [Tag]
|
||||
WHERE [DriverInstanceId] IN (
|
||||
SELECT [DriverInstanceId] FROM [DriverInstance]
|
||||
WHERE [NamespaceId] IN (
|
||||
SELECT [NamespaceId] FROM [Namespace] WHERE [Kind] = 'SystemPlatform')));
|
||||
|
||||
-- ExternalIdReservation is NOT generation-versioned and must outlive equipment deletion as a
|
||||
-- RELEASE, not a delete: active rows (ReleasedAt IS NULL) hold a fleet-wide unique reservation of
|
||||
-- the ZTag/SAPID under a filtered unique index. If we left them active after dropping the
|
||||
-- Equipment, the same external IDs could never be reused. Release them so the IDs free up while the
|
||||
-- audit row survives. Run BEFORE the Equipment DELETE so the EquipmentUuid subquery still resolves.
|
||||
UPDATE [ExternalIdReservation]
|
||||
SET [ReleasedAt] = SYSUTCDATETIME(),
|
||||
[ReleasedBy] = 'CleanupSystemPlatformNamespaces',
|
||||
[ReleaseReason] = 'Equipment removed by SystemPlatform-namespace cleanup migration (retired NamespaceKind).'
|
||||
WHERE [ReleasedAt] IS NULL
|
||||
AND [EquipmentUuid] IN (
|
||||
SELECT [EquipmentUuid] FROM [Equipment]
|
||||
WHERE [DriverInstanceId] IN (
|
||||
SELECT [DriverInstanceId] FROM [DriverInstance]
|
||||
WHERE [NamespaceId] IN (
|
||||
SELECT [NamespaceId] FROM [Namespace] WHERE [Kind] = 'SystemPlatform')));
|
||||
|
||||
-- Grandchildren of the affected Equipment ------------------------------------------------
|
||||
-- ScriptedAlarmState is keyed by ScriptedAlarm.ScriptedAlarmId; remove before its ScriptedAlarm.
|
||||
DELETE FROM [ScriptedAlarmState]
|
||||
|
||||
Reference in New Issue
Block a user