- Added Jellyfin.Database.Providers.Postgres project with full EF Core migration support for PostgreSQL. - Implemented automatic database creation and privilege assignment on startup. - Generated initial migration and model snapshot for PostgreSQL schema. - Updated build, test, and dependency files to include PostgreSQL provider and Npgsql packages. - Added PowerShell script for generating and testing PostgreSQL migrations. - No changes to application logic outside database provider/migration infrastructure.
7.5 KiB
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:
// From JellyfinMigrationService.cs lines 113-118
var databaseCreator = dbContext.Database.GetService<IDatabaseCreator>() as IRelationalDatabaseCreator;
if (!await databaseCreator.ExistsAsync().ConfigureAwait(false))
{
await databaseCreator.CreateAsync().ConfigureAwait(false);
}
What happens:
- Checks if database exists
- If not, creates the database
- Creates the
__EFMigrationsHistorytable to track applied migrations - 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.cs20200613202153_AddUsers.cs20241020103111_LibraryDbMigration.cs
PostgreSQL: Currently has NO migration files yet ⚠️
B. Code Migrations (Data Migrations)
These handle data transformations and post-schema setup tasks.
// From JellyfinMigrationService.cs lines 459-460
var migrator = _jellyfinDbContext.GetService<IMigrator>();
await migrator.MigrateAsync(_databaseMigrationInfo.Key).ConfigureAwait(false);
3. Migration Stages
Migrations run in specific stages during startup:
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
.csmigration files insrc\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:
# 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():
// 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:
sqlite3 data/jellyfin.db ".tables"
PostgreSQL:
psql -U jellyfin -d jellyfin -c "\dt"
You should see all the tables listed above.
Checking Migration History
PostgreSQL:
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:
- Check logs for migration errors
- Verify database connection
- Ensure migrations exist in the provider assembly
- Manually run:
dotnet ef database update
PostgreSQL: No Tables Created
Cause: PostgreSQL provider has no migration files
Solution: Generate migrations:
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:
- Check database user has CREATE TABLE permissions
- Verify connection string
- Check logs:
<config-dir>/logs/ - Restore from backup if available
Best Practices
For Development
- Keep migrations in sync between providers
- Test migrations before deploying
- Backup database before applying migrations
- Use source control for migration files
For Production
- Never use EnsureCreated() - always use migrations
- Backup before upgrades that include migrations
- Test migrations in staging environment first
- Monitor logs during first startup with new database
For Contributors
If adding new tables/columns:
- Update
JellyfinDbContextwith new DbSets - Generate migrations for ALL providers (SQLite, PostgreSQL)
- Test migration on clean database
- 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.