Add automatic SQL script execution for empty database initialization
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
"operationId": "02bc6448-a69d-4ff4-a0ec-0db07ec3a09a",
|
||||
"description": "Upgrade solution or project to new version of .NET",
|
||||
"startTime": "2026-03-05T22:18:32.3921759Z",
|
||||
"lastUpdateTime": "2026-03-07T17:59:55.6322536Z",
|
||||
"lastUpdateTime": "2026-03-07T18:05:10.0632722Z",
|
||||
"stage": "Execution",
|
||||
"properties": {},
|
||||
"folderPath": ""
|
||||
|
||||
+89
-13
@@ -380,11 +380,89 @@ public sealed class PostgresDatabaseProvider : IJellyfinDatabaseProvider
|
||||
var context = await DbContextFactory!.CreateDbContextAsync(cancellationToken).ConfigureAwait(false);
|
||||
await using (context.ConfigureAwait(false))
|
||||
{
|
||||
// DISABLED for .NET 11 preview: EnsureCreatedAsync bypasses migrations and creates schema directly
|
||||
// This prevents proper migration tracking. Use manual SQL scripts instead.
|
||||
// await context.Database.EnsureCreatedAsync(cancellationToken).ConfigureAwait(false);
|
||||
// Check if database is empty (no schema or no tables) and initialize if needed
|
||||
var connection = context.Database.GetDbConnection();
|
||||
var wasConnectionOpened = false;
|
||||
|
||||
logger.LogInformation("Database schema creation disabled for .NET 11 preview. Database must be initialized using SQL scripts in sql/schema_init/ directory.");
|
||||
try
|
||||
{
|
||||
if (connection.State != System.Data.ConnectionState.Open)
|
||||
{
|
||||
await connection.OpenAsync(cancellationToken).ConfigureAwait(false);
|
||||
wasConnectionOpened = true;
|
||||
}
|
||||
|
||||
// Check if the library schema exists
|
||||
var schemaCheckQuery = "SELECT COUNT(*) FROM information_schema.schemata WHERE schema_name = 'library'";
|
||||
await using (var schemaCheckCommand = connection.CreateCommand())
|
||||
{
|
||||
schemaCheckCommand.CommandText = schemaCheckQuery;
|
||||
var schemaExists = (long?)await schemaCheckCommand.ExecuteScalarAsync(cancellationToken).ConfigureAwait(false);
|
||||
|
||||
if (schemaExists == 0)
|
||||
{
|
||||
logger.LogInformation("Database is empty (library schema not found). Attempting to initialize from SQL script...");
|
||||
|
||||
// Try to load and execute create_database_schema.sql
|
||||
var schemaScriptPath = Path.Combine(AppContext.BaseDirectory, "sql", "schema_init", "create_database_schema.sql");
|
||||
|
||||
if (File.Exists(schemaScriptPath))
|
||||
{
|
||||
logger.LogInformation("Found schema script at: {Path}", schemaScriptPath);
|
||||
logger.LogInformation("Executing create_database_schema.sql to initialize database...");
|
||||
|
||||
try
|
||||
{
|
||||
var schemaScript = await File.ReadAllTextAsync(schemaScriptPath, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
// Execute the schema creation script
|
||||
await using (var schemaCommand = connection.CreateCommand())
|
||||
{
|
||||
schemaCommand.CommandText = schemaScript;
|
||||
schemaCommand.CommandTimeout = 600; // 10 minutes for large schema creation
|
||||
await schemaCommand.ExecuteNonQueryAsync(cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
logger.LogInformation("Successfully initialized database from SQL script");
|
||||
}
|
||||
catch (Exception scriptEx)
|
||||
{
|
||||
logger.LogError(scriptEx, "Failed to execute schema creation script. You may need to run it manually: {Path}", schemaScriptPath);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.LogError("Database is empty but schema script not found at: {Path}", schemaScriptPath);
|
||||
logger.LogError("Please create the database manually using the SQL script from sql/schema_init/create_database_schema.sql");
|
||||
throw new FileNotFoundException($"Schema initialization script not found: {schemaScriptPath}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// DISABLED for .NET 11 preview: EnsureCreatedAsync bypasses migrations and creates schema directly
|
||||
// This prevents proper migration tracking. Use manual SQL scripts instead.
|
||||
// await context.Database.EnsureCreatedAsync(cancellationToken).ConfigureAwait(false);
|
||||
|
||||
logger.LogInformation("Database schema verification complete.");
|
||||
|
||||
// Close connection before getting migrations to allow EF to manage connections
|
||||
if (wasConnectionOpened && connection.State == System.Data.ConnectionState.Open)
|
||||
{
|
||||
await connection.CloseAsync().ConfigureAwait(false);
|
||||
wasConnectionOpened = false;
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Ensure connection is closed on error
|
||||
if (wasConnectionOpened && connection.State == System.Data.ConnectionState.Open)
|
||||
{
|
||||
await connection.CloseAsync().ConfigureAwait(false);
|
||||
}
|
||||
|
||||
throw;
|
||||
}
|
||||
|
||||
// Get applied migrations
|
||||
var appliedMigrations = await context.Database.GetAppliedMigrationsAsync(cancellationToken).ConfigureAwait(false);
|
||||
@@ -446,17 +524,15 @@ public sealed class PostgresDatabaseProvider : IJellyfinDatabaseProvider
|
||||
}
|
||||
|
||||
// Verify all expected tables exist in each schema
|
||||
var connection = context.Database.GetDbConnection();
|
||||
var wasOpened = false;
|
||||
// Reopen connection for verification
|
||||
if (connection.State != System.Data.ConnectionState.Open)
|
||||
{
|
||||
await connection.OpenAsync(cancellationToken).ConfigureAwait(false);
|
||||
wasConnectionOpened = true;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (connection.State != System.Data.ConnectionState.Open)
|
||||
{
|
||||
await connection.OpenAsync(cancellationToken).ConfigureAwait(false);
|
||||
wasOpened = true;
|
||||
}
|
||||
|
||||
foreach (var schema in Schemas.All)
|
||||
{
|
||||
// Count tables in the schema
|
||||
@@ -490,7 +566,7 @@ public sealed class PostgresDatabaseProvider : IJellyfinDatabaseProvider
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (wasOpened)
|
||||
if (wasConnectionOpened && connection.State == System.Data.ConnectionState.Open)
|
||||
{
|
||||
await connection.CloseAsync().ConfigureAwait(false);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user