# 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.
