Summary
Every database provider's assemblies are loaded on any run, whichever provider the config actually names. That means a PostgreSQL-only user still loads — and still ships — the SQL Server, MySQL and CockroachDB providers, along with System.Data.SqlClient, MySql.Data and Npgsql.
Why it happens
SelectDbProvider, EnsureDb, DropDb and SelectJournal in ConfigurationHelper each reference every provider inside a single method body. The CLR resolves a method's assembly references when that method is JIT-compiled, so calling any one of them pulls in all of them.
Reproduction
Install the tool, delete one provider assembly you do not use, and run a PostgreSQL migration:
rm ~/.dotnet/tools/.store/dbup-cli/1.8.1/dbup-cli/1.8.1/tools/net7.0/any/dbup-cockroachdb.dll
dbup upgrade --ensure
Could not load file or assembly 'dbup-cockroachdb, Version=1.0.4.0,
Culture=neutral, PublicKeyToken=null'. The system cannot find the file specified.
It fails before it reads the config.
Why it matters
Beyond startup cost, it means unused providers cannot be removed from a container image. System.Data.SqlClient 4.6.0 as shipped is CVE-2024-0056, and today there is no way for a PostgreSQL user to drop it — the tool stops working.
Suggested fix
Route each provider's work through a small [MethodImpl(MethodImplOptions.NoInlining)] method whose signature uses only dbup-core types. The dispatching switch then names no provider type directly, so its JIT does not resolve them. NoInlining is the load-bearing part — without it the JIT can fold the body back into the caller.
No behaviour change: same providers, same order, same errors.
I have a patch with before/after verification — building master and the patched branch, deleting every non-PostgreSQL provider assembly from each, and running a real 171-script migration against PostgreSQL 16. master fails as above; the patched build reports Upgrade successful. PR follows.
Summary
Every database provider's assemblies are loaded on any run, whichever provider the config actually names. That means a PostgreSQL-only user still loads — and still ships — the SQL Server, MySQL and CockroachDB providers, along with
System.Data.SqlClient,MySql.DataandNpgsql.Why it happens
SelectDbProvider,EnsureDb,DropDbandSelectJournalinConfigurationHelpereach reference every provider inside a single method body. The CLR resolves a method's assembly references when that method is JIT-compiled, so calling any one of them pulls in all of them.Reproduction
Install the tool, delete one provider assembly you do not use, and run a PostgreSQL migration:
It fails before it reads the config.
Why it matters
Beyond startup cost, it means unused providers cannot be removed from a container image.
System.Data.SqlClient4.6.0 as shipped is CVE-2024-0056, and today there is no way for a PostgreSQL user to drop it — the tool stops working.Suggested fix
Route each provider's work through a small
[MethodImpl(MethodImplOptions.NoInlining)]method whose signature uses onlydbup-coretypes. The dispatching switch then names no provider type directly, so its JIT does not resolve them.NoInliningis the load-bearing part — without it the JIT can fold the body back into the caller.No behaviour change: same providers, same order, same errors.
I have a patch with before/after verification — building
masterand the patched branch, deleting every non-PostgreSQL provider assembly from each, and running a real 171-script migration against PostgreSQL 16.masterfails as above; the patched build reportsUpgrade successful. PR follows.