a3eb4b1b57
- 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.
255 lines
7.5 KiB
Markdown
255 lines
7.5 KiB
Markdown
# 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<IDatabaseCreator>() 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<IMigrator>();
|
|
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: `<config-dir>/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.
|