Files
jobtrackingapp/JobTrackerApi/Migrations/20260815175236_AddCrossFeatureAiUsage.cs
T
cesnimda 74a1e0d845
CI and Deploy / test (pull_request) Successful in 5m19s
CI and Deploy / deploy (pull_request) Has been skipped
fix(db): repair fresh migration chain
2026-08-15 20:47:36 +02:00

140 lines
7.1 KiB
C#

using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace JobTrackerApi.Migrations
{
/// <inheritdoc />
public partial class AddCrossFeatureAiUsage : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
// AiInteractions was historically reconciler-owned and its migration is intentionally
// a no-op. A blank standalone EF chain still needs an empty source table for the
// content-free legacy backfill below; application startup already created the same
// table, so CREATE IF NOT EXISTS preserves existing rows and mixed-version startup.
migrationBuilder.Sql(ActiveProvider.Contains("MySql", StringComparison.OrdinalIgnoreCase)
? """
CREATE TABLE IF NOT EXISTS `AiInteractions` (
`Id` int NOT NULL AUTO_INCREMENT,
`OwnerUserId` varchar(255) NOT NULL,
`JobApplicationId` int NOT NULL,
`Module` varchar(64) NOT NULL,
`Mode` longtext NULL,
`Title` longtext NOT NULL,
`Provider` longtext NOT NULL,
`ResultJson` longtext NOT NULL,
`InputCharacterCount` int NOT NULL DEFAULT 0,
`OutputCharacterCount` int NOT NULL DEFAULT 0,
`EstimatedTokenCount` int NOT NULL DEFAULT 0,
`CreatedAtUtc` datetime(6) NOT NULL,
CONSTRAINT `PK_AiInteractions` PRIMARY KEY (`Id`),
CONSTRAINT `FK_AiInteractions_JobApplications_JobApplicationId`
FOREIGN KEY (`JobApplicationId`) REFERENCES `JobApplications` (`Id`) ON DELETE CASCADE
) CHARACTER SET=utf8mb4;
"""
: """
CREATE TABLE IF NOT EXISTS "AiInteractions" (
"Id" INTEGER NOT NULL CONSTRAINT "PK_AiInteractions" PRIMARY KEY AUTOINCREMENT,
"OwnerUserId" TEXT NOT NULL,
"JobApplicationId" INTEGER NOT NULL,
"Module" TEXT NOT NULL,
"Mode" TEXT NULL,
"Title" TEXT NOT NULL,
"Provider" TEXT NOT NULL,
"ResultJson" TEXT NOT NULL,
"InputCharacterCount" INTEGER NOT NULL DEFAULT 0,
"OutputCharacterCount" INTEGER NOT NULL DEFAULT 0,
"EstimatedTokenCount" INTEGER NOT NULL DEFAULT 0,
"CreatedAtUtc" TEXT NOT NULL,
CONSTRAINT "FK_AiInteractions_JobApplications_JobApplicationId"
FOREIGN KEY ("JobApplicationId") REFERENCES "JobApplications" ("Id") ON DELETE CASCADE
);
""");
if (ActiveProvider.Contains("MySql", StringComparison.OrdinalIgnoreCase))
{
migrationBuilder.Sql("""
CREATE TABLE `AiUsageRecords` (
`Id` bigint NOT NULL AUTO_INCREMENT,
`OwnerUserId` varchar(255) NOT NULL,
`SourceType` varchar(32) NOT NULL,
`SourceId` varchar(64) NOT NULL,
`TaskType` varchar(64) NOT NULL,
`CallCount` int NOT NULL,
`InputCharacterCount` int NOT NULL,
`OutputCharacterCount` int NOT NULL,
`EstimatedTokenCount` int NOT NULL,
`CreatedAtUtc` datetime(6) NOT NULL,
CONSTRAINT `PK_AiUsageRecords` PRIMARY KEY (`Id`)
) CHARACTER SET=utf8mb4;
""");
}
else
{
migrationBuilder.CreateTable(
name: "AiUsageRecords",
columns: table => new
{
Id = table.Column<long>(type: "INTEGER", nullable: false)
.Annotation("Sqlite:Autoincrement", true),
OwnerUserId = table.Column<string>(type: "TEXT", maxLength: 255, nullable: false),
SourceType = table.Column<string>(type: "TEXT", maxLength: 32, nullable: false),
SourceId = table.Column<string>(type: "TEXT", maxLength: 64, nullable: false),
TaskType = table.Column<string>(type: "TEXT", maxLength: 64, nullable: false),
CallCount = table.Column<int>(type: "INTEGER", nullable: false),
InputCharacterCount = table.Column<int>(type: "INTEGER", nullable: false),
OutputCharacterCount = table.Column<int>(type: "INTEGER", nullable: false),
EstimatedTokenCount = table.Column<int>(type: "INTEGER", nullable: false),
CreatedAtUtc = table.Column<DateTimeOffset>(type: "TEXT", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_AiUsageRecords", x => x.Id);
});
}
migrationBuilder.CreateIndex(
name: "IX_AiUsageRecords_OwnerUserId_CreatedAtUtc",
table: "AiUsageRecords",
columns: new[] { "OwnerUserId", "CreatedAtUtc" });
migrationBuilder.CreateIndex(
name: "IX_AiUsageRecords_OwnerUserId_SourceType_SourceId",
table: "AiUsageRecords",
columns: new[] { "OwnerUserId", "SourceType", "SourceId" },
unique: true);
if (ActiveProvider.Contains("MySql", StringComparison.OrdinalIgnoreCase))
{
migrationBuilder.Sql("""
INSERT IGNORE INTO `AiUsageRecords`
(`OwnerUserId`, `SourceType`, `SourceId`, `TaskType`, `CallCount`, `InputCharacterCount`, `OutputCharacterCount`, `EstimatedTokenCount`, `CreatedAtUtc`)
SELECT `OwnerUserId`, 'workspace-legacy', CAST(`Id` AS CHAR), `Module`, 1,
`InputCharacterCount`, `OutputCharacterCount`, `EstimatedTokenCount`, `CreatedAtUtc`
FROM `AiInteractions`;
""");
}
else
{
migrationBuilder.Sql("""
INSERT OR IGNORE INTO "AiUsageRecords"
("OwnerUserId", "SourceType", "SourceId", "TaskType", "CallCount", "InputCharacterCount", "OutputCharacterCount", "EstimatedTokenCount", "CreatedAtUtc")
SELECT "OwnerUserId", 'workspace-legacy', CAST("Id" AS TEXT), "Module", 1,
"InputCharacterCount", "OutputCharacterCount", "EstimatedTokenCount", "CreatedAtUtc"
FROM "AiInteractions";
""");
}
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "AiUsageRecords");
}
}
}