Provider support
QueryGuard captures commands through EF Core's relational interceptor API. SQL grouping depends on the provider's SQL format, so test coverage varies.
The matrix
| Provider | Coverage |
|---|---|
| SQLite | Live CI tests on Ubuntu and Windows, on .NET 8 and 10 |
| PostgreSQL (Npgsql) | Live CI tests with Testcontainers |
| SQL Server | Live CI tests with Testcontainers |
| MySQL | Live CI tests with Oracle's provider; see below |
| MariaDB | Community use; no live test suite |
| Other relational providers | Best effort; SQL grouping may need more tests |
| Non-relational EF providers | Unsupported |
Integration-tested means real database commands run in CI. Fixture-verified means saved SQL is tested without a live database. See support policy.
The MySQL provider caveat
The suite uses MySql.EntityFrameworkCore from Oracle.
Pomelo SQL is not covered by this suite. Test your application's queries if you use Pomelo.
Parameter syntaxes the normalizer handles
These parameter references become one common placeholder:
| Syntax | Common use |
|---|---|
@p0, @__city_0 |
SQL Server, SQLite, MySQL |
$1, $2 |
PostgreSQL positional parameters |
:name |
Named parameters |
? |
Positional parameters |
PostgreSQL :: casts are preserved.
What is not normalized
Identifier quoting stays unchanged. "Departments", [Departments], and
`Departments` can produce different fingerprints.
Fingerprint allowlists can therefore differ between providers. Use a query tag for an exception that should apply across providers.
Running the provider suite
dotnet test tests/QueryGuard.ProviderTests
SQLite runs without Docker. With Docker running, the PostgreSQL, SQL Server, and MySQL tests run too. Container tests skip when Docker is unavailable locally; CI runs them.
Using an untested provider
Check the SQL shown in reports:
| What you see | Possible cause |
|---|---|
| One logical query has several IDs | SQL differences are not normalized |
| Different queries share one ID | Normalization or redaction removed a meaningful difference |
Open a provider report with synthetic or fully redacted SQL.
What the live SQL Server suite found
SQL Server can put SET statements before an insert:
SET IMPLICIT_TRANSACTIONS OFF;
SET NOCOUNT ON;
INSERT INTO [Departments] ([Id], [CompanyId], [Name]) VALUES (@p0, @p1, @p2);
Earlier classification counted this as a read. QueryGuard now checks statement boundaries throughout the batch. See query classification.
What the live MySQL suite found
A QueryGuard directive in a line comment could make the reported SQL look commented out after whitespace normalization. Directives now use block comments:
/*QueryGuard:Ignore reason=bounded-reference-lookup*/ SELECT `c`.`Id` FROM `Companies` AS `c`
Line and block forms of the same directive now share an ID. Review fingerprint allowlists when upgrading from the old behavior.
Widening the matrix
A new integration-tested provider needs a live test suite and someone to maintain it. SQL fixtures are also welcome.