SET ANSI_NULLS ON; GO SET QUOTED_IDENTIFIER ON; GO IF COL_LENGTH(N'dbo.Characters', N'AvatarSourceCharacterImageID') IS NULL ALTER TABLE dbo.Characters ADD AvatarSourceCharacterImageID int NULL; GO IF COL_LENGTH(N'dbo.Characters', N'AvatarImagePath') IS NULL ALTER TABLE dbo.Characters ADD AvatarImagePath nvarchar(500) NULL; GO IF COL_LENGTH(N'dbo.Characters', N'AvatarThumbnailPath') IS NULL ALTER TABLE dbo.Characters ADD AvatarThumbnailPath nvarchar(500) NULL; GO IF OBJECT_ID(N'dbo.CharacterImages', N'U') IS NULL BEGIN CREATE TABLE dbo.CharacterImages ( CharacterImageID int IDENTITY(1,1) NOT NULL CONSTRAINT PK_CharacterImages PRIMARY KEY, CharacterID int NOT NULL, ProjectID int NOT NULL, ImagePath nvarchar(500) NOT NULL, ThumbnailPath nvarchar(500) NOT NULL, Caption nvarchar(500) NULL, SortOrder int NOT NULL CONSTRAINT DF_CharacterImages_SortOrder DEFAULT (0), UploadedDateUTC datetime2 NOT NULL CONSTRAINT DF_CharacterImages_UploadedDateUTC DEFAULT (SYSUTCDATETIME()), IsDeleted bit NOT NULL CONSTRAINT DF_CharacterImages_IsDeleted DEFAULT (0), DeletedDateUTC datetime2 NULL, CONSTRAINT FK_CharacterImages_Characters FOREIGN KEY (CharacterID) REFERENCES dbo.Characters(CharacterID), CONSTRAINT FK_CharacterImages_Projects FOREIGN KEY (ProjectID) REFERENCES dbo.Projects(ProjectID) ); END; GO IF NOT EXISTS (SELECT 1 FROM sys.indexes WHERE name = N'IX_CharacterImages_CharacterID_IsDeleted_SortOrder' AND object_id = OBJECT_ID(N'dbo.CharacterImages')) CREATE INDEX IX_CharacterImages_CharacterID_IsDeleted_SortOrder ON dbo.CharacterImages(CharacterID, IsDeleted, SortOrder, UploadedDateUTC, CharacterImageID); GO INSERT dbo.CharacterImages (CharacterID, ProjectID, ImagePath, ThumbnailPath, Caption, SortOrder, UploadedDateUTC) SELECT c.CharacterID, c.ProjectID, c.ImagePath, COALESCE(c.ThumbnailPath, c.ImagePath), N'Original character image', 0, COALESCE(c.UpdatedDate, SYSUTCDATETIME()) FROM dbo.Characters c WHERE NULLIF(LTRIM(RTRIM(c.ImagePath)), N'') IS NOT NULL AND NOT EXISTS ( SELECT 1 FROM dbo.CharacterImages ci WHERE ci.CharacterID = c.CharacterID AND ci.ImagePath = c.ImagePath AND ci.IsDeleted = 0 ); GO CREATE OR ALTER PROCEDURE dbo.Character_ListByProject @ProjectID int AS BEGIN SET NOCOUNT ON; SELECT CharacterID, ProjectID, CharacterName, ShortName, Sex, BirthDate, AgeAtSeriesStart, AgeReferenceSceneID, Height, EyeColour, CharacterImportance, ShowInQuickAddBar, DefaultDescription, ImagePath, ThumbnailPath, AvatarSourceCharacterImageID, AvatarImagePath, AvatarThumbnailPath, CreatedDate, UpdatedDate, IsArchived, ArchivedDate, ArchivedReason FROM dbo.Characters WHERE ProjectID = @ProjectID AND IsArchived = 0 ORDER BY CharacterName; END; GO CREATE OR ALTER PROCEDURE dbo.Character_Get @CharacterID int AS BEGIN SET NOCOUNT ON; SELECT CharacterID, ProjectID, CharacterName, ShortName, Sex, BirthDate, AgeAtSeriesStart, AgeReferenceSceneID, Height, EyeColour, CharacterImportance, ShowInQuickAddBar, DefaultDescription, ImagePath, ThumbnailPath, AvatarSourceCharacterImageID, AvatarImagePath, AvatarThumbnailPath, CreatedDate, UpdatedDate, IsArchived, ArchivedDate, ArchivedReason FROM dbo.Characters WHERE CharacterID = @CharacterID AND IsArchived = 0; END; GO CREATE OR ALTER PROCEDURE dbo.Character_Save @CharacterID int = NULL, @ProjectID int, @CharacterName nvarchar(200), @ShortName nvarchar(100) = NULL, @Sex nvarchar(50) = NULL, @BirthDate date = NULL, @AgeAtSeriesStart int = NULL, @AgeReferenceSceneID int = NULL, @Height nvarchar(50) = NULL, @EyeColour nvarchar(50) = NULL, @CharacterImportance int = NULL, @ShowInQuickAddBar bit = 0, @DefaultDescription nvarchar(max) = NULL, @ImagePath nvarchar(500) = NULL, @ThumbnailPath nvarchar(500) = NULL AS BEGIN SET NOCOUNT ON; IF @CharacterID IS NULL OR @CharacterID = 0 BEGIN INSERT dbo.Characters (ProjectID, CharacterName, ShortName, Sex, BirthDate, AgeAtSeriesStart, AgeReferenceSceneID, Height, EyeColour, CharacterImportance, ShowInQuickAddBar, DefaultDescription, ImagePath, ThumbnailPath) VALUES (@ProjectID, @CharacterName, @ShortName, @Sex, @BirthDate, @AgeAtSeriesStart, @AgeReferenceSceneID, @Height, @EyeColour, @CharacterImportance, @ShowInQuickAddBar, @DefaultDescription, @ImagePath, @ThumbnailPath); SET @CharacterID = CAST(SCOPE_IDENTITY() AS int); END ELSE BEGIN UPDATE dbo.Characters SET CharacterName = @CharacterName, ShortName = @ShortName, Sex = @Sex, BirthDate = @BirthDate, AgeAtSeriesStart = @AgeAtSeriesStart, AgeReferenceSceneID = @AgeReferenceSceneID, Height = @Height, EyeColour = @EyeColour, CharacterImportance = @CharacterImportance, ShowInQuickAddBar = @ShowInQuickAddBar, DefaultDescription = @DefaultDescription, ImagePath = @ImagePath, ThumbnailPath = @ThumbnailPath, UpdatedDate = SYSUTCDATETIME() WHERE CharacterID = @CharacterID; END SELECT @CharacterID; END; GO CREATE OR ALTER PROCEDURE dbo.Character_UpdateImage @CharacterID int, @ImagePath nvarchar(500) = NULL, @ThumbnailPath nvarchar(500) = NULL AS BEGIN SET NOCOUNT ON; UPDATE dbo.Characters SET ImagePath = @ImagePath, ThumbnailPath = @ThumbnailPath, UpdatedDate = SYSUTCDATETIME() WHERE CharacterID = @CharacterID; END; GO CREATE OR ALTER PROCEDURE dbo.Character_UpdateAvatar @CharacterID int, @AvatarSourceCharacterImageID int = NULL, @AvatarImagePath nvarchar(500) = NULL, @AvatarThumbnailPath nvarchar(500) = NULL AS BEGIN SET NOCOUNT ON; UPDATE dbo.Characters SET AvatarSourceCharacterImageID = @AvatarSourceCharacterImageID, AvatarImagePath = @AvatarImagePath, AvatarThumbnailPath = @AvatarThumbnailPath, UpdatedDate = SYSUTCDATETIME() WHERE CharacterID = @CharacterID; END; GO CREATE OR ALTER PROCEDURE dbo.SceneCharacter_ListByScene @SceneID int AS BEGIN SET NOCOUNT ON; SELECT sc.SceneCharacterID, sc.SceneID, sc.CharacterID, c.ProjectID, CASE WHEN c.IsArchived = 1 THEN CONCAT(c.CharacterName, N' (archived)') ELSE c.CharacterName END AS CharacterName, c.ShortName, COALESCE(c.AvatarImagePath, c.ImagePath) AS CharacterImagePath, COALESCE(c.AvatarThumbnailPath, c.ThumbnailPath) AS CharacterThumbnailPath, c.BirthDate, c.AgeAtSeriesStart, sc.RoleInSceneTypeID, role.TypeName AS RoleInSceneTypeName, sc.PresenceTypeID, presence.TypeName AS PresenceTypeName, sc.LocationID, location.LocationName, location.LocationPath, sc.EntryLocationID, entryLocation.LocationName AS EntryLocationName, sc.ExitLocationID, exitLocation.LocationName AS ExitLocationName, sc.AppearanceNotes, sc.OutfitDescription, sc.PhysicalCondition, sc.EmotionalState, sc.KnowledgeNotes, sc.CreatedDate, sc.UpdatedDate FROM dbo.SceneCharacters sc INNER JOIN dbo.Characters c ON c.CharacterID = sc.CharacterID LEFT JOIN dbo.CharacterRoleInSceneTypes role ON role.CharacterRoleInSceneTypeID = sc.RoleInSceneTypeID LEFT JOIN dbo.PresenceTypes presence ON presence.PresenceTypeID = sc.PresenceTypeID LEFT JOIN dbo.LocationPaths location ON location.LocationID = sc.LocationID LEFT JOIN dbo.LocationPaths entryLocation ON entryLocation.LocationID = sc.EntryLocationID LEFT JOIN dbo.LocationPaths exitLocation ON exitLocation.LocationID = sc.ExitLocationID WHERE sc.SceneID = @SceneID ORDER BY role.SortOrder, c.CharacterName; END; GO