# Database Schema Creation - How It Works ## Yes! The Database Schema is Created Automatically Jellyfin has a sophisticated migration system that **automatically creates all database tables** when you first run it with a new database provider. ## How It Works ### 1. **First-Time Initialization** (New Installation) When Jellyfin starts for the first time: ```csharp // From JellyfinMigrationService.cs lines 113-118 var databaseCreator = dbContext.Database.GetService() as IRelationalDatabaseCreator; if (!await databaseCreator.ExistsAsync().ConfigureAwait(false)) { await databaseCreator.CreateAsync().ConfigureAwait(false); } ``` **What happens:** 1. Checks if database exists 2. If not, **creates the database** 3. Creates the `__EFMigrationsHistory` table to track applied migrations 4. Seeds initial migration records ### 2. **Migration Application** The `JellyfinMigrationService` manages two types of migrations: #### A. **Database Migrations** (EF Core Schema Migrations) These create the actual tables, columns, indexes, and constraints. **SQLite**: Has 75+ migration files (as of current version) - Located in: `src\Jellyfin.Database\Jellyfin.Database.Providers.Sqlite\Migrations\` - Examples: - `20200514181226_AddActivityLog.cs` - `20200613202153_AddUsers.cs` - `20241020103111_LibraryDbMigration.cs` **PostgreSQL**: Currently has **NO migration files yet** ⚠️ #### B. **Code Migrations** (Data Migrations) These handle data transformations and post-schema setup tasks. ```csharp // From JellyfinMigrationService.cs lines 459-460 var migrator = _jellyfinDbContext.GetService(); await migrator.MigrateAsync(_databaseMigrationInfo.Key).ConfigureAwait(false); ``` ### 3. **Migration Stages** Migrations run in specific stages during startup: ```csharp public enum JellyfinMigrationStageTypes { PreStartup, CoreInitialisation, // <- Database schema created here PostStartup } ``` **CoreInitialisation Stage** is where: - EF Core migrations are applied - Database schema (tables) is created - Indexes and constraints are added ## Current PostgreSQL Status ### ⚠️ **Important**: PostgreSQL Migrations Need to Be Generated The PostgreSQL provider is **missing EF Core migration files**. This means: ❌ **What's Missing:** - No `.cs` migration files in `src\Jellyfin.Database\Jellyfin.Database.Providers.Postgres\Migrations\` - Schema won't be created automatically for PostgreSQL - First run will fail or create empty database ✅ **What Exists:** - `PostgresDesignTimeJellyfinDbFactory.cs` - Design-time factory for generating migrations - PostgreSQL provider implementation - Connection and configuration code ### How to Generate PostgreSQL Migrations You need to generate the initial migration that creates all tables: ```bash # Navigate to the PostgreSQL provider project cd src\Jellyfin.Database\Jellyfin.Database.Providers.Postgres # Generate initial migration (creates all tables) dotnet ef migrations add InitialCreate --context JellyfinDbContext --output-dir Migrations # Or, copy and adapt migrations from SQLite provider # This is more complex but ensures parity with SQLite schema ``` ### Alternative: Runtime Schema Creation (Development Only) For development/testing, you could modify the code to use `EnsureCreated()`: ```csharp // WARNING: Only for development - bypasses migration system await dbContext.Database.EnsureCreatedAsync().ConfigureAwait(false); ``` ⚠️ **Don't use in production** - this bypasses the migration history system. ## What Gets Created When migrations run properly, they create these tables: ### Core Tables (from JellyfinDbContext.cs) - **Users** - User accounts - **Permissions** - User permissions - **Preferences** - User preferences - **AccessSchedules** - Access time restrictions - **ActivityLogs** - Activity/audit logs - **ApiKeys** - API authentication keys - **Devices** - Client devices - **DeviceOptions** - Device-specific settings - **DisplayPreferences** - UI display settings - **ItemDisplayPreferences** - Item-specific display settings - **CustomItemDisplayPreferences** - Custom item preferences - **ImageInfos** - Image metadata - **TrickplayInfos** - Video preview thumbnails metadata - **MediaSegments** - Video chapter/intro/credits data ### Library Tables (from BaseItemRepository) - **BaseItems** - Media library items (movies, shows, etc.) - **AncestorIds** - Item hierarchy relationships - **AttachmentStreamInfos** - Subtitle/attachment metadata - **Chapters** - Video chapter information - **ItemValues** - Genre/Studio/Artist tags - **ItemValuesMap** - Tag-to-item relationships - **MediaStreamInfos** - Audio/video stream metadata - **UserData** - Watch history, ratings, favorites ### System Tables - **__EFMigrationsHistory** - Tracks applied migrations ## Verifying Schema Creation ### After Jellyfin Starts Successfully **SQLite:** ```bash sqlite3 data/jellyfin.db ".tables" ``` **PostgreSQL:** ```bash psql -U jellyfin -d jellyfin -c "\dt" ``` You should see all the tables listed above. ### Checking Migration History **PostgreSQL:** ```sql SELECT * FROM "__EFMigrationsHistory" ORDER BY "MigrationId"; ``` This shows which migrations have been applied. ## Troubleshooting ### Error: "Table does not exist" **Cause:** Migrations haven't been applied **Solution:** 1. Check logs for migration errors 2. Verify database connection 3. Ensure migrations exist in the provider assembly 4. Manually run: `dotnet ef database update` ### PostgreSQL: No Tables Created **Cause:** PostgreSQL provider has no migration files **Solution:** Generate migrations: ```bash cd src\Jellyfin.Database\Jellyfin.Database.Providers.Postgres dotnet ef migrations add InitialCreate --context JellyfinDbContext ``` ### Migration Fails **Cause:** Database permissions, connection issues, or corrupt migration **Solution:** 1. Check database user has CREATE TABLE permissions 2. Verify connection string 3. Check logs: `/logs/` 4. Restore from backup if available ## Best Practices ### For Development 1. **Keep migrations in sync** between providers 2. **Test migrations** before deploying 3. **Backup database** before applying migrations 4. **Use source control** for migration files ### For Production 1. **Never use EnsureCreated()** - always use migrations 2. **Backup before upgrades** that include migrations 3. **Test migrations** in staging environment first 4. **Monitor logs** during first startup with new database ### For Contributors If adding new tables/columns: 1. **Update `JellyfinDbContext`** with new DbSets 2. **Generate migrations** for ALL providers (SQLite, PostgreSQL) 3. **Test migration** on clean database 4. **Include migration** in pull request ## Migration Workflow ``` Startup → Check Database Exists → Create if Missing ↓ Load Migration History ↓ Find Pending Migrations (compare applied vs available) ↓ Apply Each Migration in Order: - Database Migrations (schema changes) - Code Migrations (data transformations) ↓ Update Migration History ↓ Continue Jellyfin Startup ``` ## Summary **Question:** Is there code to create the database and tables? **Answer:** **YES!** - ✅ Database creation: Automatic via `IDatabaseCreator` - ✅ Table schema: Via EF Core migrations - ✅ Migration tracking: Via `__EFMigrationsHistory` - ✅ Automatic application: Via `JellyfinMigrationService` - ⚠️ PostgreSQL: **Requires migration files to be generated first** The system is fully automatic **once migrations exist** for your database provider. SQLite is ready to go. PostgreSQL needs its migrations generated using the `dotnet ef migrations add` command.