using Microsoft.EntityFrameworkCore.Migrations; #nullable disable namespace SVSim.Database.Migrations { /// public partial class RefactorGameConfigurationToJsonb : Migration { /// protected override void Up(MigrationBuilder migrationBuilder) { // Step 1: Add the new jsonb column FIRST so the backfill SQL can read the old columns. migrationBuilder.AddColumn( name: "Config", table: "GameConfigurations", type: "jsonb", nullable: false, defaultValue: ""); // Step 2: Backfill — project old flat columns into the new jsonb document. // For fresh-install databases (no pre-existing rows) this is a no-op; the // DefaultSettingsSeeder InsertData in the previous migration already seeded the // parent row, so the UPDATE below covers it. PackRates defaults are hard-coded // here because the old schema had no equivalent columns. // Use provider-specific SQL: PostgreSQL jsonb functions vs SQLite json functions. migrationBuilder.Sql( """ UPDATE "GameConfigurations" SET "Config" = jsonb_build_object( 'DefaultGrants', jsonb_build_object( 'Crystals', "DefaultCrystals", 'Rupees', "DefaultRupees", 'Ether', "DefaultEther" ), 'Player', jsonb_build_object( 'MaxFriends', "MaxFriends" ), 'DefaultLoadout', jsonb_build_object( 'DegreeId', "DefaultDegreeId", 'EmblemId', "DefaultEmblemId", 'MyPageBackgroundId', "DefaultMyPageBackgroundId", 'SleeveId', "DefaultSleeveId" ), 'Challenge', jsonb_build_object( 'UseTwoPickPremiumCard', "ChallengeUseTwoPickPremiumCard", 'TwoPickSleeveId', "ChallengeTwoPickSleeveId" ), 'Rotation', jsonb_build_object( 'TsRotationId', "TsRotationId", 'IsBattlePassPeriod', "IsBattlePassPeriod", 'IsBeginnerMission', "IsBeginnerMission", 'CardSetIdForResourceDlView', "CardSetIdForResourceDlView" ), 'PackRates', jsonb_build_object( 'AnimatedRate', 0.08, 'Default', jsonb_build_object('Bronze', 0.6744, 'Silver', 0.25, 'Gold', 0.06, 'Legendary', 0.015), 'PerSlot', jsonb_build_array( jsonb_build_object('Slot', '8', 'Bronze', 0, 'Silver', 0.7692, 'Gold', 0.1846, 'Legendary', 0.0462) ) ) ) WHERE "Id" = 'default'; """, suppressTransaction: true); // For SQLite (tests): use json() and json_object() functions. migrationBuilder.Sql( """ UPDATE "GameConfigurations" SET "Config" = json('{"DefaultGrants":{"Crystals":'||COALESCE("DefaultCrystals", 0)||',"Rupees":'||COALESCE("DefaultRupees", 0)||',"Ether":'||COALESCE("DefaultEther", 0)||'},'|| '"Player":{"MaxFriends":'||COALESCE("MaxFriends", 0)||'},'|| '"DefaultLoadout":{"DegreeId":'||COALESCE("DefaultDegreeId", 0)||',"EmblemId":'||COALESCE("DefaultEmblemId", 0)||',"MyPageBackgroundId":'||COALESCE("DefaultMyPageBackgroundId", 0)||',"SleeveId":'||COALESCE("DefaultSleeveId", 0)||'},'|| '"Challenge":{"UseTwoPickPremiumCard":'||(CASE WHEN "ChallengeUseTwoPickPremiumCard" THEN 'true' ELSE 'false' END)||',"TwoPickSleeveId":'||COALESCE("ChallengeTwoPickSleeveId", 0)||'},'|| '"Rotation":{"TsRotationId":"'||COALESCE("TsRotationId", '')||'","IsBattlePassPeriod":'||(CASE WHEN "IsBattlePassPeriod" THEN 'true' ELSE 'false' END)||',"IsBeginnerMission":'||(CASE WHEN "IsBeginnerMission" THEN 'true' ELSE 'false' END)||',"CardSetIdForResourceDlView":'||COALESCE("CardSetIdForResourceDlView", 0)||'},'|| '"PackRates":{"AnimatedRate":0.08,"Default":{"Bronze":0.6744,"Silver":0.25,"Gold":0.06,"Legendary":0.015},"PerSlot":[{"Slot":"8","Bronze":0,"Silver":0.7692,"Gold":0.1846,"Legendary":0.0462}]}'|| '}') WHERE "Id" = 'default'; """, suppressTransaction: true); // Step 3: Drop FK constraints, indexes, and old flat columns. migrationBuilder.DropForeignKey( name: "FK_GameConfigurations_Degrees_DefaultDegreeId", table: "GameConfigurations"); migrationBuilder.DropForeignKey( name: "FK_GameConfigurations_Emblems_DefaultEmblemId", table: "GameConfigurations"); migrationBuilder.DropForeignKey( name: "FK_GameConfigurations_MyPageBackgrounds_DefaultMyPageBackgroun~", table: "GameConfigurations"); migrationBuilder.DropForeignKey( name: "FK_GameConfigurations_Sleeves_DefaultSleeveId", table: "GameConfigurations"); migrationBuilder.DropIndex( name: "IX_GameConfigurations_DefaultDegreeId", table: "GameConfigurations"); migrationBuilder.DropIndex( name: "IX_GameConfigurations_DefaultEmblemId", table: "GameConfigurations"); migrationBuilder.DropIndex( name: "IX_GameConfigurations_DefaultMyPageBackgroundId", table: "GameConfigurations"); migrationBuilder.DropIndex( name: "IX_GameConfigurations_DefaultSleeveId", table: "GameConfigurations"); migrationBuilder.DropColumn( name: "CardSetIdForResourceDlView", table: "GameConfigurations"); migrationBuilder.DropColumn( name: "ChallengeTwoPickSleeveId", table: "GameConfigurations"); migrationBuilder.DropColumn( name: "ChallengeUseTwoPickPremiumCard", table: "GameConfigurations"); migrationBuilder.DropColumn( name: "DefaultCrystals", table: "GameConfigurations"); migrationBuilder.DropColumn( name: "DefaultDegreeId", table: "GameConfigurations"); migrationBuilder.DropColumn( name: "DefaultEmblemId", table: "GameConfigurations"); migrationBuilder.DropColumn( name: "DefaultEther", table: "GameConfigurations"); migrationBuilder.DropColumn( name: "DefaultMyPageBackgroundId", table: "GameConfigurations"); migrationBuilder.DropColumn( name: "DefaultRupees", table: "GameConfigurations"); migrationBuilder.DropColumn( name: "DefaultSleeveId", table: "GameConfigurations"); migrationBuilder.DropColumn( name: "IsBattlePassPeriod", table: "GameConfigurations"); migrationBuilder.DropColumn( name: "IsBeginnerMission", table: "GameConfigurations"); migrationBuilder.DropColumn( name: "MaxFriends", table: "GameConfigurations"); migrationBuilder.DropColumn( name: "TsRotationId", table: "GameConfigurations"); } /// protected override void Down(MigrationBuilder migrationBuilder) { migrationBuilder.DropColumn( name: "Config", table: "GameConfigurations"); migrationBuilder.AddColumn( name: "CardSetIdForResourceDlView", table: "GameConfigurations", type: "integer", nullable: false, defaultValue: 0); migrationBuilder.AddColumn( name: "ChallengeTwoPickSleeveId", table: "GameConfigurations", type: "bigint", nullable: false, defaultValue: 0L); migrationBuilder.AddColumn( name: "ChallengeUseTwoPickPremiumCard", table: "GameConfigurations", type: "boolean", nullable: false, defaultValue: false); migrationBuilder.AddColumn( name: "DefaultCrystals", table: "GameConfigurations", type: "numeric(20,0)", nullable: false, defaultValue: 0m); migrationBuilder.AddColumn( name: "DefaultDegreeId", table: "GameConfigurations", type: "integer", nullable: false, defaultValue: 0); migrationBuilder.AddColumn( name: "DefaultEmblemId", table: "GameConfigurations", type: "integer", nullable: false, defaultValue: 0); migrationBuilder.AddColumn( name: "DefaultEther", table: "GameConfigurations", type: "numeric(20,0)", nullable: false, defaultValue: 0m); migrationBuilder.AddColumn( name: "DefaultMyPageBackgroundId", table: "GameConfigurations", type: "integer", nullable: false, defaultValue: 0); migrationBuilder.AddColumn( name: "DefaultRupees", table: "GameConfigurations", type: "numeric(20,0)", nullable: false, defaultValue: 0m); migrationBuilder.AddColumn( name: "DefaultSleeveId", table: "GameConfigurations", type: "integer", nullable: false, defaultValue: 0); migrationBuilder.AddColumn( name: "IsBattlePassPeriod", table: "GameConfigurations", type: "boolean", nullable: false, defaultValue: false); migrationBuilder.AddColumn( name: "IsBeginnerMission", table: "GameConfigurations", type: "boolean", nullable: false, defaultValue: false); migrationBuilder.AddColumn( name: "MaxFriends", table: "GameConfigurations", type: "integer", nullable: false, defaultValue: 0); migrationBuilder.AddColumn( name: "TsRotationId", table: "GameConfigurations", type: "text", nullable: false, defaultValue: ""); migrationBuilder.UpdateData( table: "GameConfigurations", keyColumn: "Id", keyValue: "default", columns: new[] { "CardSetIdForResourceDlView", "ChallengeTwoPickSleeveId", "ChallengeUseTwoPickPremiumCard", "DefaultCrystals", "DefaultDegreeId", "DefaultEmblemId", "DefaultEther", "DefaultMyPageBackgroundId", "DefaultRupees", "DefaultSleeveId", "IsBattlePassPeriod", "IsBeginnerMission", "MaxFriends", "TsRotationId" }, values: new object[] { 0, 0L, false, 50000m, 300003, 100000000, 50000m, 100000000, 50000m, 3000011, false, false, 20, "" }); migrationBuilder.CreateIndex( name: "IX_GameConfigurations_DefaultDegreeId", table: "GameConfigurations", column: "DefaultDegreeId"); migrationBuilder.CreateIndex( name: "IX_GameConfigurations_DefaultEmblemId", table: "GameConfigurations", column: "DefaultEmblemId"); migrationBuilder.CreateIndex( name: "IX_GameConfigurations_DefaultMyPageBackgroundId", table: "GameConfigurations", column: "DefaultMyPageBackgroundId"); migrationBuilder.CreateIndex( name: "IX_GameConfigurations_DefaultSleeveId", table: "GameConfigurations", column: "DefaultSleeveId"); migrationBuilder.AddForeignKey( name: "FK_GameConfigurations_Degrees_DefaultDegreeId", table: "GameConfigurations", column: "DefaultDegreeId", principalTable: "Degrees", principalColumn: "Id", onDelete: ReferentialAction.Cascade); migrationBuilder.AddForeignKey( name: "FK_GameConfigurations_Emblems_DefaultEmblemId", table: "GameConfigurations", column: "DefaultEmblemId", principalTable: "Emblems", principalColumn: "Id", onDelete: ReferentialAction.Cascade); migrationBuilder.AddForeignKey( name: "FK_GameConfigurations_MyPageBackgrounds_DefaultMyPageBackgroun~", table: "GameConfigurations", column: "DefaultMyPageBackgroundId", principalTable: "MyPageBackgrounds", principalColumn: "Id", onDelete: ReferentialAction.Cascade); migrationBuilder.AddForeignKey( name: "FK_GameConfigurations_Sleeves_DefaultSleeveId", table: "GameConfigurations", column: "DefaultSleeveId", principalTable: "Sleeves", principalColumn: "Id", onDelete: ReferentialAction.Cascade); } } }