Skip to content

Commit 922c089

Browse files
authored
Catch exception instead of trying to check if the history repository exists (#3294)
Fixes #2878
1 parent 87a1a7e commit 922c089

File tree

1 file changed

+54
-16
lines changed

1 file changed

+54
-16
lines changed

src/EFCore.PG/Migrations/Internal/NpgsqlHistoryRepository.cs

Lines changed: 54 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -75,22 +75,8 @@ private RelationalCommandParameterObject CreateRelationalCommandParameters()
7575
/// doing so can result in application failures when updating to a new Entity Framework Core release.
7676
/// </summary>
7777
protected override string ExistsSql
78-
{
79-
get
80-
{
81-
var stringTypeMapping = Dependencies.TypeMappingSource.GetMapping(typeof(string));
82-
83-
return
84-
$"""
85-
SELECT EXISTS (
86-
SELECT 1 FROM pg_catalog.pg_class c
87-
JOIN pg_catalog.pg_namespace n ON n.oid=c.relnamespace
88-
WHERE n.nspname={stringTypeMapping.GenerateSqlLiteral(TableSchema ?? "public")} AND
89-
c.relname={stringTypeMapping.GenerateSqlLiteral(TableName)}
90-
)
91-
""";
92-
}
93-
}
78+
=> throw new UnreachableException(
79+
"We should not be checking for the existence of the history table, but rather creating it and catching exceptions (see below)");
9480

9581
/// <summary>
9682
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
@@ -194,6 +180,58 @@ public override string GetEndIfScript()
194180
END $EF$;
195181
""";
196182

183+
/// <summary>
184+
/// Calls the base implementation, but catches "table not found" exceptions; we do this rather than try to detect whether the
185+
/// migration table already exists (see <see cref="ExistsAsync" /> override below), since it's difficult to reliably check if the
186+
/// migration history table exists or not (because user may set PG <c>search_path</c>, which determines unqualified tables
187+
/// references when creating, selecting).
188+
/// </summary>
189+
public override IReadOnlyList<HistoryRow> GetAppliedMigrations()
190+
{
191+
try
192+
{
193+
return base.GetAppliedMigrations();
194+
}
195+
catch (PostgresException e) when (e.SqlState is "3D000" or "42P01")
196+
{
197+
return [];
198+
}
199+
}
200+
201+
/// <summary>
202+
/// Calls the base implementation, but catches "table not found" exceptions; we do this rather than try to detect whether the
203+
/// migration table already exists (see <see cref="ExistsAsync" /> override below), since it's difficult to reliably check if the
204+
/// migration history table exists or not (because user may set PG <c>search_path</c>, which determines unqualified tables
205+
/// references when creating, selecting).
206+
/// </summary>
207+
public override async Task<IReadOnlyList<HistoryRow>> GetAppliedMigrationsAsync(CancellationToken cancellationToken = default)
208+
{
209+
try
210+
{
211+
return await base.GetAppliedMigrationsAsync(cancellationToken).ConfigureAwait(false);
212+
}
213+
catch (PostgresException e) when (e.SqlState is "3D000" or "42P01")
214+
{
215+
return [];
216+
}
217+
}
218+
219+
/// <summary>
220+
/// Always returns <see langword="true" /> for PostgreSQL - it's difficult to reliably check if the migration history table
221+
/// exists or not (because user may set PG <c>search_path</c>, which determines unqualified tables references when creating,
222+
/// selecting). So we instead catch the "table doesn't exist" exceptions instead.
223+
/// </summary>
224+
public override bool Exists()
225+
=> true;
226+
227+
/// <summary>
228+
/// Always returns <see langword="true" /> for PostgreSQL - it's difficult to reliably check if the migration history table
229+
/// exists or not (because user may set PG <c>search_path</c>, which determines unqualified tables references when creating,
230+
/// selecting). So we instead catch the "table doesn't exist" exceptions instead.
231+
/// </summary>
232+
public override Task<bool> ExistsAsync(CancellationToken cancellationToken = default)
233+
=> Task.FromResult(true);
234+
197235
private sealed class NpgsqlMigrationDatabaseLock(IHistoryRepository historyRepository) : IMigrationsDatabaseLock
198236
{
199237
/// <summary>

0 commit comments

Comments
 (0)