155 lines
5.7 KiB
C#
155 lines
5.7 KiB
C#
using System;
|
|
using Microsoft.EntityFrameworkCore;
|
|
|
|
namespace RolemasterDb.App.Data;
|
|
|
|
public static class RolemasterDbSchemaUpgrader
|
|
{
|
|
public static async Task EnsureLatestAsync(RolemasterDbContext dbContext, CancellationToken cancellationToken = default)
|
|
{
|
|
await EnsureAttackTableFumbleColumnsAsync(dbContext, cancellationToken);
|
|
|
|
await dbContext.Database.ExecuteSqlRawAsync(
|
|
"""
|
|
CREATE TABLE IF NOT EXISTS "CriticalBranches" (
|
|
"Id" INTEGER NOT NULL CONSTRAINT "PK_CriticalBranches" PRIMARY KEY AUTOINCREMENT,
|
|
"CriticalResultId" INTEGER NOT NULL,
|
|
"BranchKind" TEXT NOT NULL,
|
|
"ConditionKey" TEXT NULL,
|
|
"ConditionText" TEXT NOT NULL,
|
|
"ConditionJson" TEXT NOT NULL,
|
|
"RawText" TEXT NOT NULL,
|
|
"DescriptionText" TEXT NOT NULL,
|
|
"RawAffixText" TEXT NULL,
|
|
"ParsedJson" TEXT NOT NULL,
|
|
"SortOrder" INTEGER NOT NULL,
|
|
CONSTRAINT "FK_CriticalBranches_CriticalResults_CriticalResultId"
|
|
FOREIGN KEY ("CriticalResultId") REFERENCES "CriticalResults" ("Id") ON DELETE CASCADE
|
|
);
|
|
""",
|
|
cancellationToken);
|
|
|
|
await dbContext.Database.ExecuteSqlRawAsync(
|
|
"""
|
|
CREATE INDEX IF NOT EXISTS "IX_CriticalBranches_CriticalResultId"
|
|
ON "CriticalBranches" ("CriticalResultId");
|
|
""",
|
|
cancellationToken);
|
|
|
|
await dbContext.Database.ExecuteSqlRawAsync(
|
|
"""
|
|
CREATE INDEX IF NOT EXISTS "IX_CriticalBranches_CriticalResultId_SortOrder"
|
|
ON "CriticalBranches" ("CriticalResultId", "SortOrder");
|
|
""",
|
|
cancellationToken);
|
|
|
|
await dbContext.Database.ExecuteSqlRawAsync(
|
|
"""
|
|
CREATE TABLE IF NOT EXISTS "CriticalEffects" (
|
|
"Id" INTEGER NOT NULL CONSTRAINT "PK_CriticalEffects" PRIMARY KEY AUTOINCREMENT,
|
|
"CriticalResultId" INTEGER NULL,
|
|
"CriticalBranchId" INTEGER NULL,
|
|
"EffectCode" TEXT NOT NULL,
|
|
"Target" TEXT NULL,
|
|
"ValueInteger" INTEGER NULL,
|
|
"ValueDecimal" TEXT NULL,
|
|
"ValueExpression" TEXT NULL,
|
|
"DurationRounds" INTEGER NULL,
|
|
"PerRound" INTEGER NULL,
|
|
"Modifier" INTEGER NULL,
|
|
"BodyPart" TEXT NULL,
|
|
"IsPermanent" INTEGER NOT NULL,
|
|
"SourceType" TEXT NOT NULL,
|
|
"SourceText" TEXT NULL,
|
|
CONSTRAINT "FK_CriticalEffects_CriticalResults_CriticalResultId"
|
|
FOREIGN KEY ("CriticalResultId") REFERENCES "CriticalResults" ("Id") ON DELETE CASCADE,
|
|
CONSTRAINT "FK_CriticalEffects_CriticalBranches_CriticalBranchId"
|
|
FOREIGN KEY ("CriticalBranchId") REFERENCES "CriticalBranches" ("Id") ON DELETE CASCADE
|
|
);
|
|
""",
|
|
cancellationToken);
|
|
|
|
await dbContext.Database.ExecuteSqlRawAsync(
|
|
"""
|
|
CREATE INDEX IF NOT EXISTS "IX_CriticalEffects_EffectCode"
|
|
ON "CriticalEffects" ("EffectCode");
|
|
""",
|
|
cancellationToken);
|
|
|
|
await dbContext.Database.ExecuteSqlRawAsync(
|
|
"""
|
|
CREATE INDEX IF NOT EXISTS "IX_CriticalEffects_CriticalResultId"
|
|
ON "CriticalEffects" ("CriticalResultId");
|
|
""",
|
|
cancellationToken);
|
|
|
|
await dbContext.Database.ExecuteSqlRawAsync(
|
|
"""
|
|
CREATE INDEX IF NOT EXISTS "IX_CriticalEffects_CriticalBranchId"
|
|
ON "CriticalEffects" ("CriticalBranchId");
|
|
""",
|
|
cancellationToken);
|
|
}
|
|
|
|
private static async Task EnsureAttackTableFumbleColumnsAsync(RolemasterDbContext dbContext, CancellationToken cancellationToken)
|
|
{
|
|
if (!await ColumnExistsAsync(dbContext, "AttackTables", "FumbleMinRoll", cancellationToken))
|
|
{
|
|
await dbContext.Database.ExecuteSqlRawAsync(
|
|
"""
|
|
ALTER TABLE "AttackTables"
|
|
ADD COLUMN "FumbleMinRoll" INTEGER NULL;
|
|
""",
|
|
cancellationToken);
|
|
}
|
|
|
|
if (!await ColumnExistsAsync(dbContext, "AttackTables", "FumbleMaxRoll", cancellationToken))
|
|
{
|
|
await dbContext.Database.ExecuteSqlRawAsync(
|
|
"""
|
|
ALTER TABLE "AttackTables"
|
|
ADD COLUMN "FumbleMaxRoll" INTEGER NULL;
|
|
""",
|
|
cancellationToken);
|
|
}
|
|
}
|
|
|
|
private static async Task<bool> ColumnExistsAsync(
|
|
RolemasterDbContext dbContext,
|
|
string tableName,
|
|
string columnName,
|
|
CancellationToken cancellationToken)
|
|
{
|
|
var connection = dbContext.Database.GetDbConnection();
|
|
var shouldClose = connection.State != System.Data.ConnectionState.Open;
|
|
if (shouldClose)
|
|
{
|
|
await connection.OpenAsync(cancellationToken);
|
|
}
|
|
|
|
try
|
|
{
|
|
await using var command = connection.CreateCommand();
|
|
command.CommandText = $"PRAGMA table_info(\"{tableName}\");";
|
|
|
|
await using var reader = await command.ExecuteReaderAsync(cancellationToken);
|
|
while (await reader.ReadAsync(cancellationToken))
|
|
{
|
|
if (string.Equals(reader["name"]?.ToString(), columnName, StringComparison.Ordinal))
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
finally
|
|
{
|
|
if (shouldClose)
|
|
{
|
|
await connection.CloseAsync();
|
|
}
|
|
}
|
|
}
|
|
}
|