SQL Dialects
BifrostQL abstracts database-specific SQL generation through the ISqlDialect interface. Each dialect handles identifier quoting, pagination syntax, type mapping, and upsert strategies for its target database.
Supported databases
Section titled “Supported databases”| Database | Package | Provider key | Status |
|---|---|---|---|
| SQL Server | BifrostQL.SqlServer | sqlserver | Production |
| PostgreSQL | BifrostQL.Ngsql | postgres | Production |
| MySQL | BifrostQL.MySql | mysql | Production |
| SQLite | BifrostQL.Sqlite | sqlite | Experimental |
Set the provider in configuration:
{ "BifrostQL": { "Provider": "postgres" }}Dialect differences
Section titled “Dialect differences”Identifier quoting
Section titled “Identifier quoting”| Database | Style | Example |
|---|---|---|
| SQL Server | Brackets | [orders].[orderId] |
| PostgreSQL | Double quotes | "orders"."orderId" |
| MySQL | Backticks | `orders`.`orderId` |
| SQLite | Double quotes | "orders"."orderId" |
Pagination
Section titled “Pagination”| Database | Syntax |
|---|---|
| SQL Server | OFFSET @offset ROWS FETCH NEXT @limit ROWS ONLY |
| PostgreSQL | LIMIT @limit OFFSET @offset |
| MySQL | LIMIT @limit OFFSET @offset |
| SQLite | LIMIT @limit OFFSET @offset |
SQL Server requires an ORDER BY clause for OFFSET/FETCH pagination. BifrostQL adds a default order by primary key when no sort is specified.
Upsert strategy
Section titled “Upsert strategy”| Database | Implementation |
|---|---|
| SQL Server | MERGE ... WHEN MATCHED THEN UPDATE WHEN NOT MATCHED THEN INSERT |
| PostgreSQL | INSERT ... ON CONFLICT (pk) DO UPDATE SET ... |
| MySQL | INSERT ... ON DUPLICATE KEY UPDATE ... |
| SQLite | INSERT OR REPLACE INTO ... |
Type mapping specifics
Section titled “Type mapping specifics”SQL Server:
money,smallmoneymap toDecimaluniqueidentifiermaps toStringnvarchar,nchar,ntextmap toString
PostgreSQL:
serial,bigserialare treated as auto-incrementuuidmaps toStringjsonb,jsonmap toStringtext[],integer[]map to[String],[Int]
MySQL:
tinyint(1)maps toBoolean(MySqlConnector returnsboolfor this type)enumcolumns map toStringjsonmaps toString- Column names are case-insensitive
SQLite:
- Type affinity rules apply:
INTEGER,REAL,TEXT,BLOB - No native
BOOLEAN— usesINTEGERwith 0/1 - No native
DATETIME— stored as text in ISO 8601 format
Installing a dialect
Section titled “Installing a dialect”Add the dialect package alongside the core server package:
# SQL Serverdotnet add package BifrostQL.SqlServer
# PostgreSQLdotnet add package BifrostQL.Ngsql
# MySQLdotnet add package BifrostQL.MySql
# SQLitedotnet add package BifrostQL.SqliteThe dialect is selected at startup based on the Provider configuration value. Each dialect registers its own type mapper and SQL generator with the BifrostQL pipeline.
Writing a custom dialect
Section titled “Writing a custom dialect”Implement the ISqlDialect interface to add support for a new database. The dialect must provide:
- Identifier quoting
- Parameter placeholder style
- Pagination SQL generation
- Upsert SQL generation
- Type mapper (SQL types to GraphQL types)
- Schema reader (database metadata to
DbModel)
Register the dialect in your service configuration before calling AddBifrostQL.