Fix permanent project hard delete dependencies
This commit is contained in:
parent
3740658f3e
commit
dc5232378f
@ -180,16 +180,23 @@ static void ProjectHardDeleteClearsStoryIntelligenceDependenciesInTransaction()
|
|||||||
var root = Path.Combine(AppContext.BaseDirectory, "../../../../PlotLine");
|
var root = Path.Combine(AppContext.BaseDirectory, "../../../../PlotLine");
|
||||||
var repository = File.ReadAllText(Path.Combine(root, "Data/Repositories.cs"));
|
var repository = File.ReadAllText(Path.Combine(root, "Data/Repositories.cs"));
|
||||||
var cascadeMigration = File.ReadAllText(Path.Combine(root, "Sql/159_Phase25D_ManuscriptSourceHardDeleteCascades.sql"));
|
var cascadeMigration = File.ReadAllText(Path.Combine(root, "Sql/159_Phase25D_ManuscriptSourceHardDeleteCascades.sql"));
|
||||||
|
var dependencyCleanupMigration = File.ReadAllText(Path.Combine(root, "Sql/160_Phase25E_ProjectHardDeleteDependencyCleanup.sql"));
|
||||||
|
|
||||||
Assert(repository.Contains("using var transaction = connection.BeginTransaction()", StringComparison.Ordinal), "Project hard delete should be wrapped by a repository transaction.");
|
Assert(repository.Contains("using var transaction = connection.BeginTransaction()", StringComparison.Ordinal), "Project hard delete should be wrapped by a repository transaction.");
|
||||||
Assert(repository.Contains("ProjectHardDeleteStoryIntelligenceDependencyCleanupSql", StringComparison.Ordinal), "Project hard delete should run scoped Story Intelligence dependency cleanup before the stored procedure.");
|
Assert(repository.Contains("\"dbo.ProjectHardDelete_PrepareDependencies\"", StringComparison.Ordinal), "Project hard delete should run scoped dependency cleanup through a stored procedure.");
|
||||||
|
Assert(!repository.Contains("ProjectHardDeleteStoryIntelligenceDependencyCleanupSql", StringComparison.Ordinal), "Project hard delete should not carry dependency cleanup as inline SQL.");
|
||||||
Assert(repository.Contains("AllowActiveProject = false", StringComparison.Ordinal), "Archived-project permanent delete must refuse active projects before cleanup.");
|
Assert(repository.Contains("AllowActiveProject = false", StringComparison.Ordinal), "Archived-project permanent delete must refuse active projects before cleanup.");
|
||||||
Assert(repository.Contains("THROW 52002, 'Only archived projects can be permanently deleted.'", StringComparison.Ordinal), "Hard delete cleanup should enforce the archive gate before deleting child rows.");
|
Assert(dependencyCleanupMigration.Contains("THROW 52002, 'Only archived projects can be permanently deleted.'", StringComparison.Ordinal), "Hard delete cleanup should enforce the archive gate before deleting child rows.");
|
||||||
Assert(repository.Contains("CharacterIntelligenceEvidenceEvents", StringComparison.Ordinal), "Hard delete cleanup should remove character intelligence evidence rows.");
|
Assert(dependencyCleanupMigration.Contains("CharacterIntelligenceEvidenceEvents", StringComparison.Ordinal), "Hard delete cleanup should remove character intelligence evidence rows.");
|
||||||
Assert(repository.Contains("CharacterIntelligenceProfiles", StringComparison.Ordinal), "Hard delete cleanup should remove character intelligence profile rows.");
|
Assert(dependencyCleanupMigration.Contains("CharacterIntelligenceProfiles", StringComparison.Ordinal), "Hard delete cleanup should remove character intelligence profile rows.");
|
||||||
Assert(repository.Contains("StoryMemoryProcessedSceneResults", StringComparison.Ordinal), "Hard delete cleanup should remove durable story memory scene-result rows.");
|
Assert(dependencyCleanupMigration.Contains("StoryMemoryProcessedSceneResults", StringComparison.Ordinal), "Hard delete cleanup should remove durable story memory scene-result rows.");
|
||||||
Assert(repository.Contains("StoryMemoryImportPreferences", StringComparison.Ordinal), "Hard delete cleanup should remove durable story memory import rows.");
|
Assert(dependencyCleanupMigration.Contains("StoryMemoryImportPreferences", StringComparison.Ordinal), "Hard delete cleanup should remove durable story memory import rows.");
|
||||||
Assert(repository.Contains("WHERE ProjectID = @ProjectID", StringComparison.Ordinal), "Hard delete cleanup must be scoped by project id.");
|
Assert(dependencyCleanupMigration.Contains("SceneCharacterSuggestions", StringComparison.Ordinal), "Hard delete cleanup should remove scene character suggestion rows.");
|
||||||
|
Assert(dependencyCleanupMigration.Contains("SceneLocationSuggestions", StringComparison.Ordinal), "Hard delete cleanup should remove scene location suggestion rows.");
|
||||||
|
Assert(dependencyCleanupMigration.Contains("SceneAssetSuggestions", StringComparison.Ordinal), "Hard delete cleanup should remove scene asset suggestion rows.");
|
||||||
|
Assert(dependencyCleanupMigration.Contains("WordCompanionSceneLocations", StringComparison.Ordinal), "Hard delete cleanup should remove Word Companion scene location rows.");
|
||||||
|
Assert(dependencyCleanupMigration.Contains("WordCompanionSceneAssets", StringComparison.Ordinal), "Hard delete cleanup should remove Word Companion scene asset rows.");
|
||||||
|
Assert(dependencyCleanupMigration.Contains("WHERE ProjectID = @ProjectID", StringComparison.Ordinal), "Hard delete cleanup must be scoped by project id.");
|
||||||
Assert(cascadeMigration.Contains("FK_SceneManuscriptSources_Scenes", StringComparison.Ordinal)
|
Assert(cascadeMigration.Contains("FK_SceneManuscriptSources_Scenes", StringComparison.Ordinal)
|
||||||
&& cascadeMigration.Contains("REFERENCES dbo.Scenes(SceneID) ON DELETE CASCADE", StringComparison.Ordinal), "Scene manuscript source text should not block permanent scene deletion.");
|
&& cascadeMigration.Contains("REFERENCES dbo.Scenes(SceneID) ON DELETE CASCADE", StringComparison.Ordinal), "Scene manuscript source text should not block permanent scene deletion.");
|
||||||
Assert(cascadeMigration.Contains("FK_ManuscriptStructuralChapterSources_Chapters", StringComparison.Ordinal)
|
Assert(cascadeMigration.Contains("FK_ManuscriptStructuralChapterSources_Chapters", StringComparison.Ordinal)
|
||||||
|
|||||||
@ -2112,9 +2112,10 @@ public sealed class ProjectRepository(ISqlConnectionFactory connectionFactory) :
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
await connection.ExecuteAsync(
|
await connection.ExecuteAsync(
|
||||||
ProjectHardDeleteStoryIntelligenceDependencyCleanupSql,
|
"dbo.ProjectHardDelete_PrepareDependencies",
|
||||||
new { ProjectID = projectId, UserID = userId, AllowActiveProject = false },
|
new { ProjectID = projectId, UserID = userId, AllowActiveProject = false },
|
||||||
transaction,
|
transaction,
|
||||||
|
commandType: CommandType.StoredProcedure,
|
||||||
commandTimeout: 120);
|
commandTimeout: 120);
|
||||||
|
|
||||||
await connection.ExecuteAsync(
|
await connection.ExecuteAsync(
|
||||||
@ -2132,137 +2133,6 @@ public sealed class ProjectRepository(ISqlConnectionFactory connectionFactory) :
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private const string ProjectHardDeleteStoryIntelligenceDependencyCleanupSql = """
|
|
||||||
SET NOCOUNT ON;
|
|
||||||
|
|
||||||
IF NOT EXISTS
|
|
||||||
(
|
|
||||||
SELECT 1
|
|
||||||
FROM dbo.Projects p
|
|
||||||
INNER JOIN dbo.ProjectUserAccess pua ON pua.ProjectID = p.ProjectID
|
|
||||||
WHERE p.ProjectID = @ProjectID
|
|
||||||
AND pua.UserID = @UserID
|
|
||||||
AND pua.AccessRole = N'Owner'
|
|
||||||
AND pua.IsActive = 1
|
|
||||||
)
|
|
||||||
THROW 52001, 'Project was not found for this owner.', 1;
|
|
||||||
|
|
||||||
IF @AllowActiveProject = 0 AND EXISTS (SELECT 1 FROM dbo.Projects WHERE ProjectID = @ProjectID AND IsArchived = 0)
|
|
||||||
THROW 52002, 'Only archived projects can be permanently deleted.', 1;
|
|
||||||
|
|
||||||
DECLARE @BookIDs TABLE (BookID int NOT NULL PRIMARY KEY);
|
|
||||||
DECLARE @ChapterIDs TABLE (ChapterID int NOT NULL PRIMARY KEY);
|
|
||||||
DECLARE @SceneIDs TABLE (SceneID int NOT NULL PRIMARY KEY);
|
|
||||||
DECLARE @StoryIntelligenceRunIDs TABLE (StoryIntelligenceRunID int NOT NULL PRIMARY KEY);
|
|
||||||
DECLARE @StoryIntelligenceChapterResultIDs TABLE (ChapterResultID int NOT NULL PRIMARY KEY);
|
|
||||||
DECLARE @StoryIntelligenceSceneResultIDs TABLE (SceneResultID int NOT NULL PRIMARY KEY);
|
|
||||||
DECLARE @ImportSessionIDs TABLE (ImportSessionID int NOT NULL PRIMARY KEY);
|
|
||||||
DECLARE @CharacterIntelligenceProfileIDs TABLE (CharacterIntelligenceProfileID int NOT NULL PRIMARY KEY);
|
|
||||||
|
|
||||||
INSERT @BookIDs (BookID)
|
|
||||||
SELECT BookID FROM dbo.Books WHERE ProjectID = @ProjectID;
|
|
||||||
|
|
||||||
INSERT @ChapterIDs (ChapterID)
|
|
||||||
SELECT c.ChapterID
|
|
||||||
FROM dbo.Chapters c
|
|
||||||
INNER JOIN @BookIDs b ON b.BookID = c.BookID;
|
|
||||||
|
|
||||||
INSERT @SceneIDs (SceneID)
|
|
||||||
SELECT s.SceneID
|
|
||||||
FROM dbo.Scenes s
|
|
||||||
INNER JOIN @ChapterIDs c ON c.ChapterID = s.ChapterID;
|
|
||||||
|
|
||||||
INSERT @ImportSessionIDs (ImportSessionID)
|
|
||||||
SELECT StoryIntelligenceBookPipelineID
|
|
||||||
FROM dbo.StoryIntelligenceBookPipelines pipeline
|
|
||||||
WHERE pipeline.ProjectID = @ProjectID
|
|
||||||
OR EXISTS (SELECT 1 FROM @BookIDs b WHERE b.BookID = pipeline.BookID);
|
|
||||||
|
|
||||||
INSERT @StoryIntelligenceRunIDs (StoryIntelligenceRunID)
|
|
||||||
SELECT DISTINCT r.StoryIntelligenceRunID
|
|
||||||
FROM dbo.StoryIntelligenceRuns r
|
|
||||||
WHERE r.ProjectID = @ProjectID
|
|
||||||
OR EXISTS (SELECT 1 FROM @BookIDs b WHERE b.BookID = r.BookID)
|
|
||||||
OR EXISTS (SELECT 1 FROM @ChapterIDs c WHERE c.ChapterID = r.ChapterID)
|
|
||||||
OR EXISTS (SELECT 1 FROM @SceneIDs s INNER JOIN dbo.Scenes scene ON scene.SceneID = s.SceneID WHERE scene.ImportRunID = r.StoryIntelligenceRunID);
|
|
||||||
|
|
||||||
INSERT @StoryIntelligenceChapterResultIDs (ChapterResultID)
|
|
||||||
SELECT DISTINCT cr.ChapterResultID
|
|
||||||
FROM dbo.StoryIntelligenceChapterResults cr
|
|
||||||
WHERE cr.ProjectID = @ProjectID
|
|
||||||
OR EXISTS (SELECT 1 FROM @StoryIntelligenceRunIDs r WHERE r.StoryIntelligenceRunID = cr.StoryIntelligenceRunID)
|
|
||||||
OR EXISTS (SELECT 1 FROM @BookIDs b WHERE b.BookID = cr.BookID)
|
|
||||||
OR EXISTS (SELECT 1 FROM @ChapterIDs c WHERE c.ChapterID = cr.ChapterID);
|
|
||||||
|
|
||||||
INSERT @StoryIntelligenceSceneResultIDs (SceneResultID)
|
|
||||||
SELECT DISTINCT sr.SceneResultID
|
|
||||||
FROM dbo.StoryIntelligenceSceneResults sr
|
|
||||||
WHERE sr.ProjectID = @ProjectID
|
|
||||||
OR EXISTS (SELECT 1 FROM @StoryIntelligenceRunIDs r WHERE r.StoryIntelligenceRunID = sr.StoryIntelligenceRunID)
|
|
||||||
OR EXISTS (SELECT 1 FROM @StoryIntelligenceChapterResultIDs cr WHERE cr.ChapterResultID = sr.ChapterResultID)
|
|
||||||
OR EXISTS (SELECT 1 FROM @BookIDs b WHERE b.BookID = sr.BookID)
|
|
||||||
OR EXISTS (SELECT 1 FROM @ChapterIDs c WHERE c.ChapterID = sr.ChapterID)
|
|
||||||
OR EXISTS (SELECT 1 FROM @SceneIDs s WHERE s.SceneID = sr.SceneID);
|
|
||||||
|
|
||||||
INSERT @CharacterIntelligenceProfileIDs (CharacterIntelligenceProfileID)
|
|
||||||
SELECT DISTINCT profile.CharacterIntelligenceProfileID
|
|
||||||
FROM dbo.CharacterIntelligenceProfiles profile
|
|
||||||
WHERE EXISTS (SELECT 1 FROM @ImportSessionIDs sessionIDs WHERE sessionIDs.ImportSessionID = profile.ImportSessionID)
|
|
||||||
OR EXISTS (SELECT 1 FROM @StoryIntelligenceSceneResultIDs resultIDs WHERE resultIDs.SceneResultID = profile.LastUpdatedSceneResultID);
|
|
||||||
|
|
||||||
DELETE evidence
|
|
||||||
FROM dbo.CharacterIntelligenceEvidenceEvents evidence
|
|
||||||
WHERE EXISTS (SELECT 1 FROM @CharacterIntelligenceProfileIDs profileIDs WHERE profileIDs.CharacterIntelligenceProfileID = evidence.CharacterIntelligenceProfileID)
|
|
||||||
OR EXISTS (SELECT 1 FROM @StoryIntelligenceSceneResultIDs resultIDs WHERE resultIDs.SceneResultID = evidence.SceneResultID);
|
|
||||||
|
|
||||||
DELETE profileRows
|
|
||||||
FROM dbo.CharacterIntelligenceProfiles profileRows
|
|
||||||
WHERE EXISTS (SELECT 1 FROM @CharacterIntelligenceProfileIDs profileIDs WHERE profileIDs.CharacterIntelligenceProfileID = profileRows.CharacterIntelligenceProfileID);
|
|
||||||
|
|
||||||
DELETE FROM dbo.StoryMemoryIllustrationAssignments
|
|
||||||
WHERE EXISTS (SELECT 1 FROM @ImportSessionIDs ids WHERE ids.ImportSessionID = StoryMemoryIllustrationAssignments.ImportSessionID);
|
|
||||||
|
|
||||||
DELETE FROM dbo.StoryMemoryIllustrationDemands
|
|
||||||
WHERE EXISTS (SELECT 1 FROM @ImportSessionIDs ids WHERE ids.ImportSessionID = StoryMemoryIllustrationDemands.ImportSessionID);
|
|
||||||
|
|
||||||
DELETE FROM dbo.StoryMemoryRelationships
|
|
||||||
WHERE EXISTS (SELECT 1 FROM @ImportSessionIDs ids WHERE ids.ImportSessionID = StoryMemoryRelationships.ImportSessionID);
|
|
||||||
|
|
||||||
DELETE FROM dbo.StoryMemoryCharacterAttributes
|
|
||||||
WHERE EXISTS
|
|
||||||
(
|
|
||||||
SELECT 1
|
|
||||||
FROM dbo.StoryMemoryCharacters c
|
|
||||||
INNER JOIN @ImportSessionIDs ids ON ids.ImportSessionID = c.ImportSessionID
|
|
||||||
WHERE c.StoryMemoryCharacterID = StoryMemoryCharacterAttributes.StoryMemoryCharacterID
|
|
||||||
);
|
|
||||||
|
|
||||||
DELETE FROM dbo.StoryMemoryCharacterAliases
|
|
||||||
WHERE EXISTS
|
|
||||||
(
|
|
||||||
SELECT 1
|
|
||||||
FROM dbo.StoryMemoryCharacters c
|
|
||||||
INNER JOIN @ImportSessionIDs ids ON ids.ImportSessionID = c.ImportSessionID
|
|
||||||
WHERE c.StoryMemoryCharacterID = StoryMemoryCharacterAliases.StoryMemoryCharacterID
|
|
||||||
);
|
|
||||||
|
|
||||||
DELETE FROM dbo.StoryMemoryAssets
|
|
||||||
WHERE EXISTS (SELECT 1 FROM @ImportSessionIDs ids WHERE ids.ImportSessionID = StoryMemoryAssets.ImportSessionID);
|
|
||||||
|
|
||||||
DELETE FROM dbo.StoryMemoryLocations
|
|
||||||
WHERE EXISTS (SELECT 1 FROM @ImportSessionIDs ids WHERE ids.ImportSessionID = StoryMemoryLocations.ImportSessionID);
|
|
||||||
|
|
||||||
DELETE FROM dbo.StoryMemoryCharacters
|
|
||||||
WHERE EXISTS (SELECT 1 FROM @ImportSessionIDs ids WHERE ids.ImportSessionID = StoryMemoryCharacters.ImportSessionID);
|
|
||||||
|
|
||||||
DELETE FROM dbo.StoryMemoryProcessedSceneResults
|
|
||||||
WHERE EXISTS (SELECT 1 FROM @ImportSessionIDs ids WHERE ids.ImportSessionID = StoryMemoryProcessedSceneResults.ImportSessionID)
|
|
||||||
OR EXISTS (SELECT 1 FROM @StoryIntelligenceSceneResultIDs resultIDs WHERE resultIDs.SceneResultID = StoryMemoryProcessedSceneResults.SceneResultID);
|
|
||||||
|
|
||||||
DELETE FROM dbo.StoryMemoryImportPreferences
|
|
||||||
WHERE EXISTS (SELECT 1 FROM @ImportSessionIDs ids WHERE ids.ImportSessionID = StoryMemoryImportPreferences.ImportSessionID);
|
|
||||||
""";
|
|
||||||
|
|
||||||
public async Task<IReadOnlyList<string>> ListHardDeleteFilePathsForAccountDeletionAsync(int projectId, int userId)
|
public async Task<IReadOnlyList<string>> ListHardDeleteFilePathsForAccountDeletionAsync(int projectId, int userId)
|
||||||
{
|
{
|
||||||
using var connection = connectionFactory.CreateConnection();
|
using var connection = connectionFactory.CreateConnection();
|
||||||
@ -2282,9 +2152,10 @@ WHERE EXISTS (SELECT 1 FROM @ImportSessionIDs ids WHERE ids.ImportSessionID = St
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
await connection.ExecuteAsync(
|
await connection.ExecuteAsync(
|
||||||
ProjectHardDeleteStoryIntelligenceDependencyCleanupSql,
|
"dbo.ProjectHardDelete_PrepareDependencies",
|
||||||
new { ProjectID = projectId, UserID = userId, AllowActiveProject = true },
|
new { ProjectID = projectId, UserID = userId, AllowActiveProject = true },
|
||||||
transaction,
|
transaction,
|
||||||
|
commandType: CommandType.StoredProcedure,
|
||||||
commandTimeout: 120);
|
commandTimeout: 120);
|
||||||
|
|
||||||
await connection.ExecuteAsync(
|
await connection.ExecuteAsync(
|
||||||
|
|||||||
218
PlotLine/Sql/160_Phase25E_ProjectHardDeleteDependencyCleanup.sql
Normal file
218
PlotLine/Sql/160_Phase25E_ProjectHardDeleteDependencyCleanup.sql
Normal file
@ -0,0 +1,218 @@
|
|||||||
|
SET ANSI_NULLS ON;
|
||||||
|
GO
|
||||||
|
SET QUOTED_IDENTIFIER ON;
|
||||||
|
GO
|
||||||
|
|
||||||
|
CREATE OR ALTER PROCEDURE dbo.ProjectHardDelete_PrepareDependencies
|
||||||
|
@ProjectID int,
|
||||||
|
@UserID int,
|
||||||
|
@AllowActiveProject bit = 0
|
||||||
|
AS
|
||||||
|
BEGIN
|
||||||
|
SET NOCOUNT ON;
|
||||||
|
|
||||||
|
IF NOT EXISTS
|
||||||
|
(
|
||||||
|
SELECT 1
|
||||||
|
FROM dbo.Projects p
|
||||||
|
INNER JOIN dbo.ProjectUserAccess pua ON pua.ProjectID = p.ProjectID
|
||||||
|
WHERE p.ProjectID = @ProjectID
|
||||||
|
AND pua.UserID = @UserID
|
||||||
|
AND pua.AccessRole = N'Owner'
|
||||||
|
AND pua.IsActive = 1
|
||||||
|
)
|
||||||
|
THROW 52001, 'Project was not found for this owner.', 1;
|
||||||
|
|
||||||
|
IF @AllowActiveProject = 0 AND EXISTS (SELECT 1 FROM dbo.Projects WHERE ProjectID = @ProjectID AND IsArchived = 0)
|
||||||
|
THROW 52002, 'Only archived projects can be permanently deleted.', 1;
|
||||||
|
|
||||||
|
DECLARE @BookIDs TABLE (BookID int NOT NULL PRIMARY KEY);
|
||||||
|
DECLARE @ChapterIDs TABLE (ChapterID int NOT NULL PRIMARY KEY);
|
||||||
|
DECLARE @SceneIDs TABLE (SceneID int NOT NULL PRIMARY KEY);
|
||||||
|
DECLARE @StoryIntelligenceRunIDs TABLE (StoryIntelligenceRunID int NOT NULL PRIMARY KEY);
|
||||||
|
DECLARE @StoryIntelligenceChapterResultIDs TABLE (ChapterResultID int NOT NULL PRIMARY KEY);
|
||||||
|
DECLARE @StoryIntelligenceSceneResultIDs TABLE (SceneResultID int NOT NULL PRIMARY KEY);
|
||||||
|
DECLARE @ImportSessionIDs TABLE (ImportSessionID int NOT NULL PRIMARY KEY);
|
||||||
|
DECLARE @CharacterIntelligenceProfileIDs TABLE (CharacterIntelligenceProfileID int NOT NULL PRIMARY KEY);
|
||||||
|
|
||||||
|
INSERT @BookIDs (BookID)
|
||||||
|
SELECT BookID FROM dbo.Books WHERE ProjectID = @ProjectID;
|
||||||
|
|
||||||
|
INSERT @ChapterIDs (ChapterID)
|
||||||
|
SELECT c.ChapterID
|
||||||
|
FROM dbo.Chapters c
|
||||||
|
INNER JOIN @BookIDs b ON b.BookID = c.BookID;
|
||||||
|
|
||||||
|
INSERT @SceneIDs (SceneID)
|
||||||
|
SELECT s.SceneID
|
||||||
|
FROM dbo.Scenes s
|
||||||
|
INNER JOIN @ChapterIDs c ON c.ChapterID = s.ChapterID;
|
||||||
|
|
||||||
|
INSERT @ImportSessionIDs (ImportSessionID)
|
||||||
|
SELECT StoryIntelligenceBookPipelineID
|
||||||
|
FROM dbo.StoryIntelligenceBookPipelines pipeline
|
||||||
|
WHERE pipeline.ProjectID = @ProjectID
|
||||||
|
OR EXISTS (SELECT 1 FROM @BookIDs b WHERE b.BookID = pipeline.BookID);
|
||||||
|
|
||||||
|
INSERT @StoryIntelligenceRunIDs (StoryIntelligenceRunID)
|
||||||
|
SELECT DISTINCT r.StoryIntelligenceRunID
|
||||||
|
FROM dbo.StoryIntelligenceRuns r
|
||||||
|
WHERE r.ProjectID = @ProjectID
|
||||||
|
OR EXISTS (SELECT 1 FROM @BookIDs b WHERE b.BookID = r.BookID)
|
||||||
|
OR EXISTS (SELECT 1 FROM @ChapterIDs c WHERE c.ChapterID = r.ChapterID)
|
||||||
|
OR EXISTS (SELECT 1 FROM @SceneIDs s INNER JOIN dbo.Scenes scene ON scene.SceneID = s.SceneID WHERE scene.ImportRunID = r.StoryIntelligenceRunID);
|
||||||
|
|
||||||
|
INSERT @StoryIntelligenceChapterResultIDs (ChapterResultID)
|
||||||
|
SELECT DISTINCT cr.ChapterResultID
|
||||||
|
FROM dbo.StoryIntelligenceChapterResults cr
|
||||||
|
WHERE cr.ProjectID = @ProjectID
|
||||||
|
OR EXISTS (SELECT 1 FROM @StoryIntelligenceRunIDs r WHERE r.StoryIntelligenceRunID = cr.StoryIntelligenceRunID)
|
||||||
|
OR EXISTS (SELECT 1 FROM @BookIDs b WHERE b.BookID = cr.BookID)
|
||||||
|
OR EXISTS (SELECT 1 FROM @ChapterIDs c WHERE c.ChapterID = cr.ChapterID);
|
||||||
|
|
||||||
|
INSERT @StoryIntelligenceSceneResultIDs (SceneResultID)
|
||||||
|
SELECT DISTINCT sr.SceneResultID
|
||||||
|
FROM dbo.StoryIntelligenceSceneResults sr
|
||||||
|
WHERE sr.ProjectID = @ProjectID
|
||||||
|
OR EXISTS (SELECT 1 FROM @StoryIntelligenceRunIDs r WHERE r.StoryIntelligenceRunID = sr.StoryIntelligenceRunID)
|
||||||
|
OR EXISTS (SELECT 1 FROM @StoryIntelligenceChapterResultIDs cr WHERE cr.ChapterResultID = sr.ChapterResultID)
|
||||||
|
OR EXISTS (SELECT 1 FROM @BookIDs b WHERE b.BookID = sr.BookID)
|
||||||
|
OR EXISTS (SELECT 1 FROM @ChapterIDs c WHERE c.ChapterID = sr.ChapterID)
|
||||||
|
OR EXISTS (SELECT 1 FROM @SceneIDs s WHERE s.SceneID = sr.SceneID);
|
||||||
|
|
||||||
|
INSERT @CharacterIntelligenceProfileIDs (CharacterIntelligenceProfileID)
|
||||||
|
SELECT DISTINCT profile.CharacterIntelligenceProfileID
|
||||||
|
FROM dbo.CharacterIntelligenceProfiles profile
|
||||||
|
WHERE EXISTS (SELECT 1 FROM @ImportSessionIDs sessionIDs WHERE sessionIDs.ImportSessionID = profile.ImportSessionID)
|
||||||
|
OR EXISTS (SELECT 1 FROM @StoryIntelligenceSceneResultIDs resultIDs WHERE resultIDs.SceneResultID = profile.LastUpdatedSceneResultID);
|
||||||
|
|
||||||
|
DELETE suggestion
|
||||||
|
FROM dbo.SceneCharacterSuggestions suggestion
|
||||||
|
LEFT JOIN @SceneIDs scene ON scene.SceneID = suggestion.SceneID
|
||||||
|
LEFT JOIN dbo.Characters characterRows ON characterRows.CharacterID = suggestion.CharacterID
|
||||||
|
WHERE scene.SceneID IS NOT NULL
|
||||||
|
OR characterRows.ProjectID = @ProjectID;
|
||||||
|
|
||||||
|
DELETE suggestion
|
||||||
|
FROM dbo.SceneLocationSuggestions suggestion
|
||||||
|
LEFT JOIN @SceneIDs scene ON scene.SceneID = suggestion.SceneID
|
||||||
|
LEFT JOIN dbo.Locations locationRows ON locationRows.LocationID = suggestion.LocationID
|
||||||
|
WHERE scene.SceneID IS NOT NULL
|
||||||
|
OR locationRows.ProjectID = @ProjectID;
|
||||||
|
|
||||||
|
DELETE suggestion
|
||||||
|
FROM dbo.SceneAssetSuggestions suggestion
|
||||||
|
LEFT JOIN @SceneIDs scene ON scene.SceneID = suggestion.SceneID
|
||||||
|
LEFT JOIN dbo.StoryAssets assetRows ON assetRows.StoryAssetID = suggestion.AssetID
|
||||||
|
WHERE scene.SceneID IS NOT NULL
|
||||||
|
OR assetRows.ProjectID = @ProjectID;
|
||||||
|
|
||||||
|
DELETE sceneAssets
|
||||||
|
FROM dbo.WordCompanionSceneAssets sceneAssets
|
||||||
|
LEFT JOIN @SceneIDs scene ON scene.SceneID = sceneAssets.SceneID
|
||||||
|
LEFT JOIN dbo.StoryAssets assetRows ON assetRows.StoryAssetID = sceneAssets.StoryAssetID
|
||||||
|
WHERE scene.SceneID IS NOT NULL
|
||||||
|
OR assetRows.ProjectID = @ProjectID;
|
||||||
|
|
||||||
|
DELETE sceneLocations
|
||||||
|
FROM dbo.WordCompanionSceneLocations sceneLocations
|
||||||
|
LEFT JOIN @SceneIDs scene ON scene.SceneID = sceneLocations.SceneID
|
||||||
|
LEFT JOIN dbo.Locations locationRows ON locationRows.LocationID = sceneLocations.LocationID
|
||||||
|
WHERE scene.SceneID IS NOT NULL
|
||||||
|
OR locationRows.ProjectID = @ProjectID;
|
||||||
|
|
||||||
|
DELETE evidence
|
||||||
|
FROM dbo.CharacterIntelligenceEvidenceEvents evidence
|
||||||
|
WHERE EXISTS (SELECT 1 FROM @CharacterIntelligenceProfileIDs profileIDs WHERE profileIDs.CharacterIntelligenceProfileID = evidence.CharacterIntelligenceProfileID)
|
||||||
|
OR EXISTS (SELECT 1 FROM @StoryIntelligenceSceneResultIDs resultIDs WHERE resultIDs.SceneResultID = evidence.SceneResultID);
|
||||||
|
|
||||||
|
DELETE profileRows
|
||||||
|
FROM dbo.CharacterIntelligenceProfiles profileRows
|
||||||
|
WHERE EXISTS (SELECT 1 FROM @CharacterIntelligenceProfileIDs profileIDs WHERE profileIDs.CharacterIntelligenceProfileID = profileRows.CharacterIntelligenceProfileID);
|
||||||
|
|
||||||
|
DELETE FROM dbo.StoryMemoryIllustrationAssignments
|
||||||
|
WHERE EXISTS (SELECT 1 FROM @ImportSessionIDs ids WHERE ids.ImportSessionID = StoryMemoryIllustrationAssignments.ImportSessionID);
|
||||||
|
|
||||||
|
DELETE FROM dbo.StoryMemoryIllustrationDemands
|
||||||
|
WHERE EXISTS (SELECT 1 FROM @ImportSessionIDs ids WHERE ids.ImportSessionID = StoryMemoryIllustrationDemands.ImportSessionID);
|
||||||
|
|
||||||
|
DELETE FROM dbo.StoryMemoryRelationships
|
||||||
|
WHERE EXISTS (SELECT 1 FROM @ImportSessionIDs ids WHERE ids.ImportSessionID = StoryMemoryRelationships.ImportSessionID);
|
||||||
|
|
||||||
|
DELETE FROM dbo.StoryMemoryCharacterAttributes
|
||||||
|
WHERE EXISTS
|
||||||
|
(
|
||||||
|
SELECT 1
|
||||||
|
FROM dbo.StoryMemoryCharacters c
|
||||||
|
INNER JOIN @ImportSessionIDs ids ON ids.ImportSessionID = c.ImportSessionID
|
||||||
|
WHERE c.StoryMemoryCharacterID = StoryMemoryCharacterAttributes.StoryMemoryCharacterID
|
||||||
|
);
|
||||||
|
|
||||||
|
DELETE FROM dbo.StoryMemoryCharacterAliases
|
||||||
|
WHERE EXISTS
|
||||||
|
(
|
||||||
|
SELECT 1
|
||||||
|
FROM dbo.StoryMemoryCharacters c
|
||||||
|
INNER JOIN @ImportSessionIDs ids ON ids.ImportSessionID = c.ImportSessionID
|
||||||
|
WHERE c.StoryMemoryCharacterID = StoryMemoryCharacterAliases.StoryMemoryCharacterID
|
||||||
|
);
|
||||||
|
|
||||||
|
DELETE FROM dbo.StoryMemoryAssets
|
||||||
|
WHERE EXISTS (SELECT 1 FROM @ImportSessionIDs ids WHERE ids.ImportSessionID = StoryMemoryAssets.ImportSessionID);
|
||||||
|
|
||||||
|
DELETE FROM dbo.StoryMemoryLocations
|
||||||
|
WHERE EXISTS (SELECT 1 FROM @ImportSessionIDs ids WHERE ids.ImportSessionID = StoryMemoryLocations.ImportSessionID);
|
||||||
|
|
||||||
|
DELETE FROM dbo.StoryMemoryCharacters
|
||||||
|
WHERE EXISTS (SELECT 1 FROM @ImportSessionIDs ids WHERE ids.ImportSessionID = StoryMemoryCharacters.ImportSessionID);
|
||||||
|
|
||||||
|
DELETE FROM dbo.StoryMemoryProcessedSceneResults
|
||||||
|
WHERE EXISTS (SELECT 1 FROM @ImportSessionIDs ids WHERE ids.ImportSessionID = StoryMemoryProcessedSceneResults.ImportSessionID)
|
||||||
|
OR EXISTS (SELECT 1 FROM @StoryIntelligenceSceneResultIDs resultIDs WHERE resultIDs.SceneResultID = StoryMemoryProcessedSceneResults.SceneResultID);
|
||||||
|
|
||||||
|
DELETE FROM dbo.StoryMemoryImportPreferences
|
||||||
|
WHERE EXISTS (SELECT 1 FROM @ImportSessionIDs ids WHERE ids.ImportSessionID = StoryMemoryImportPreferences.ImportSessionID);
|
||||||
|
END;
|
||||||
|
GO
|
||||||
|
|
||||||
|
DECLARE @ProjectHardDeleteDefinition nvarchar(max) = OBJECT_DEFINITION(OBJECT_ID(N'dbo.ProjectHardDelete_ForOwner'));
|
||||||
|
|
||||||
|
IF @ProjectHardDeleteDefinition IS NOT NULL
|
||||||
|
AND @ProjectHardDeleteDefinition NOT LIKE N'%ProjectHardDelete_PrepareDependencies%'
|
||||||
|
BEGIN
|
||||||
|
SET @ProjectHardDeleteDefinition = REPLACE
|
||||||
|
(
|
||||||
|
@ProjectHardDeleteDefinition,
|
||||||
|
N' BEGIN TRANSACTION;',
|
||||||
|
N' BEGIN TRANSACTION;
|
||||||
|
|
||||||
|
EXEC dbo.ProjectHardDelete_PrepareDependencies
|
||||||
|
@ProjectID = @ProjectID,
|
||||||
|
@UserID = @UserID,
|
||||||
|
@AllowActiveProject = 0;'
|
||||||
|
);
|
||||||
|
|
||||||
|
IF @ProjectHardDeleteDefinition NOT LIKE N'%ProjectHardDelete_PrepareDependencies%'
|
||||||
|
THROW 52012, 'Project hard-delete dependency cleanup call was not inserted.', 1;
|
||||||
|
|
||||||
|
DECLARE @CreateIndex int = CHARINDEX(N'CREATE', @ProjectHardDeleteDefinition);
|
||||||
|
DECLARE @ProcedureIndex int = CHARINDEX(N'PROCEDURE', @ProjectHardDeleteDefinition);
|
||||||
|
|
||||||
|
IF @CreateIndex = 0 OR @ProcedureIndex = 0 OR @ProcedureIndex <= @CreateIndex
|
||||||
|
THROW 52013, 'Project hard-delete procedure definition could not be patched.', 1;
|
||||||
|
|
||||||
|
SET @ProjectHardDeleteDefinition = STUFF
|
||||||
|
(
|
||||||
|
@ProjectHardDeleteDefinition,
|
||||||
|
@CreateIndex,
|
||||||
|
@ProcedureIndex - @CreateIndex,
|
||||||
|
N'ALTER '
|
||||||
|
);
|
||||||
|
|
||||||
|
EXEC sys.sp_executesql @ProjectHardDeleteDefinition;
|
||||||
|
END;
|
||||||
|
GO
|
||||||
|
|
||||||
|
IF OBJECT_DEFINITION(OBJECT_ID(N'dbo.ProjectHardDelete_ForOwner')) NOT LIKE N'%ProjectHardDelete_PrepareDependencies%'
|
||||||
|
THROW 52014, 'Project hard-delete procedure does not call dependency cleanup.', 1;
|
||||||
|
GO
|
||||||
Loading…
x
Reference in New Issue
Block a user