Class SqlDialect
- Namespace
- eQuantic.Core.Data.Relational
- Assembly
- eQuantic.Core.Data.Relational.dll
A database's SQL flavour: identifier quoting, naming conventions, paging syntax, type names for DDL, and the rendering of the constructs that differ between engines (collection membership, tuple comparisons, generated-key retrieval). The shared relational engine renders everything else; a provider package is this class plus a driver.
public abstract class SqlDialect
- Inheritance
-
SqlDialect
- Derived
- Inherited Members
Constructors
SqlDialect()
Initializes the dialect with the standard function translations.
protected SqlDialect()
Properties
FalseLiteral
The literal for an always-false predicate (an empty IN); some dialects have no FALSE.
public virtual string FalseLiteral { get; }
Property Value
Functions
The function translations this dialect knows — extend it with Map(string, Func<string, IReadOnlyList<string>, string>).
public SqlFunctionRegistry Functions { get; }
Property Value
GeneratedKeyDdl
The DDL column suffix declaring a database-generated key (e.g. GENERATED BY DEFAULT AS IDENTITY).
public abstract string GeneratedKeyDdl { get; }
Property Value
IntrospectColumnsSql
A query listing every column of the schema in use, as four values in order: the table's name, the
column's name, its type spelled the way this dialect spells it in DDL, and whether it accepts
null. null when the dialect cannot read its own catalogue, which makes drift unanswerable
rather than answered wrongly.
Each dialect writes its own, and composes the type in SQL rather than leaving it to be reassembled from parts afterwards. Catalogues disagree about where a type's facets live — one keeps the whole spelling in a column, another splits length from precision from fractional seconds — and the disagreement is far better settled by the store that knows the answer.
public virtual string? IntrospectColumnsSql { get; }
Property Value
RequiresOrderByForLimit
Whether a limited query must carry an ORDER BY (SQL Server's OFFSET/FETCH); the key is used when unsorted.
public virtual bool RequiresOrderByForLimit { get; }
Property Value
SupportsBulkInsert
Whether the engine has a native bulk-load path for this dialect (PostgreSQL COPY,
SQL Server SqlBulkCopy, MySQL's bulk loader). BulkInsertAsync refuses on dialects that
answer false rather than quietly running an ordinary batch — asking for a bulk load and
getting row-by-row inserts is exactly the kind of silent cost this engine does not ship.
public virtual bool SupportsBulkInsert { get; }
Property Value
System
The OpenTelemetry db.system value (e.g. postgresql, mysql, mssql).
public abstract string System { get; }
Property Value
Methods
AddColumnSql(string, string, string)
The DDL adding a column to an existing table (added nullable, matching create-table semantics).
public virtual string AddColumnSql(string quotedTable, string quotedColumn, string sqlType)
Parameters
quotedTablestringThe quoted table.
quotedColumnstringThe quoted column.
sqlTypestringThe column's SQL type.
Returns
AlterColumnType(string, string, string)
The DDL altering a column's type (a dialect may need a cast clause).
public virtual string AlterColumnType(string quotedTable, string quotedColumn, string sqlType)
Parameters
Returns
BindValue(object?)
Converts a value before binding (a dialect may need CLR-side coercion, e.g. arrays); identity by default.
public virtual object? BindValue(object? value)
Parameters
valueobject
Returns
BulkInsertAsync(DbConnection, DbTransaction?, string, IReadOnlyList<RelationalColumn>, IReadOnlyList<object?[]>, CancellationToken)
Bulk-loads rows through the store's native mechanism. Implemented by the dialects that declare
SupportsBulkInsert; each row carries the column values in columns
order, already converted to their stored form by the engine.
public virtual Task<long> BulkInsertAsync(DbConnection connection, DbTransaction? transaction, string quotedTable, IReadOnlyList<RelationalColumn> columns, IReadOnlyList<object?[]> rows, CancellationToken cancellationToken)
Parameters
connectionDbConnectionThe open connection (inside the caller's transaction, when there is one).
transactionDbTransactionThe ambient transaction, or
null.quotedTablestringThe quoted target table.
columnsIReadOnlyList<RelationalColumn>The target columns, in the order each row's values arrive.
rowsIReadOnlyList<object[]>The rows to load.
cancellationTokenCancellationTokenThe cancellation token.
Returns
CollectionContains(string, string, bool)
Renders a collection-membership test (member CONTAINS value / CONTAINS KEY) for stores
with native collection columns; the base dialect cannot express it (the clause degrades to residual).
public virtual string CollectionContains(string column, string parameter, bool key)
Parameters
columnstringThe quoted column.
parameterstringThe bound value's parameter marker.
keyboolWhether the test targets a map key.
Returns
CollectionMutation(string, string, bool, bool)
Renders a collection-mutating SET fragment (col = col + items), for stores with collection columns.
public virtual string CollectionMutation(string column, string parameter, bool remove, bool prepend)
Parameters
columnstringThe quoted column.
parameterstringThe bound items' parameter marker.
removeboolWhether the items are removed instead of added.
prependboolWhether added items go at the front.
Returns
ColumnName(string)
Applies the naming convention to a member name to produce its column name (snake_case by default).
public virtual string ColumnName(string memberName)
Parameters
memberNamestring
Returns
ConfigureParameter(DbParameter, object?)
Configures a just-created parameter for a bound value — the hook a dialect uses to type values its
driver cannot infer (e.g. a dictionary into a jsonb parameter). The base dialect does nothing.
public virtual void ConfigureParameter(DbParameter parameter, object? value)
Parameters
parameterDbParameterThe parameter (its name and value are already set).
valueobjectThe bound value.
CreateIndexSql(string, string, string, bool)
Builds a CREATE INDEX statement (idempotent where the dialect supports it; migration history guards re-runs otherwise).
public virtual string CreateIndexSql(string quotedName, string quotedTable, string columns, bool unique)
Parameters
quotedNamestringThe quoted index name.
quotedTablestringThe quoted table.
columnsstringThe quoted key column list (with directions).
uniqueboolWhether the index enforces uniqueness.
Returns
CreateIndexSql(string, string, string, bool, IndexMethod, string?)
The DDL creating an index with a structure and an optional filtered predicate (already rendered as a SQL fragment with inlined literals). The base dialect builds default-structure indexes, filtered or not; a method it has no structure for is rejected with guidance.
public virtual string CreateIndexSql(string quotedName, string quotedTable, string columns, bool unique, IndexMethod method, string? filter)
Parameters
quotedNamestringThe quoted index name.
quotedTablestringThe quoted table.
columnsstringThe rendered key column list.
uniqueboolWhether the index enforces uniqueness.
methodIndexMethodThe index structure.
filterstringThe rendered partial-index predicate, or
null.
Returns
CreateTableSql(string, string)
Builds an idempotent CREATE TABLE statement.
public virtual string CreateTableSql(string quotedTable, string columnsDdl)
Parameters
Returns
DropColumnSql(string, string)
The DDL dropping a column from an existing table.
public virtual string DropColumnSql(string quotedTable, string quotedColumn)
Parameters
Returns
DropTableSql(string)
The DDL dropping a table, and everything that depended on it.
public virtual string DropTableSql(string quotedTable)
Parameters
quotedTablestringThe quoted table.
Returns
InsertSql(string, string, string, string?)
Builds an INSERT, reading the generated key back when returningKey is supplied
(RETURNING / OUTPUT INSERTED). The base dialect cannot read keys back — declare a
client-generated key, or use a dialect that can.
public virtual string InsertSql(string quotedTable, string columns, string values, string? returningKey)
Parameters
quotedTablestringThe quoted table.
columnsstringThe quoted column list.
valuesstringThe bound value list.
returningKeystringThe quoted generated-key column to read back, or
null.
Returns
IsDocumentColumn(Type)
Whether a member of this CLR type maps as a document column (e.g. a scalar-keyed dictionary
into PostgreSQL jsonb). The base dialect maps none — such members stay unmapped navigations.
public virtual bool IsDocumentColumn(Type type)
Parameters
typeTypeThe member's CLR type.
Returns
LimitClause(string, string?)
The SQL fragment limiting a query to the bound row count after the bound offset (appended after ORDER BY).
public virtual string LimitClause(string limitParameter, string? offsetParameter)
Parameters
Returns
Literal(object?)
Renders a value as an inline SQL literal — DDL (a filtered index's predicate) cannot carry bind parameters. Values a dialect cannot inline are rejected with guidance.
public virtual string Literal(object? value)
Parameters
valueobjectThe value (already normalized by BindValue(object?)).
Returns
NormalizeStoredType(string)
Reduces a type to one spelling, so the type this dialect would emit and the one the catalogue reports can be compared without every synonym reading as a difference.
A drift check is only worth running if a clean database is silent. Every store names some types
more than one way — character varying and varchar, int and integer —
and comparing the raw strings would report all of them, which teaches people to ignore the report.
Dialects override this with their own synonyms; the base only strips case and spacing.
public virtual string NormalizeStoredType(string storedType)
Parameters
storedTypestringA type as written in DDL or reported by the catalogue.
Returns
Quote(string)
Quotes an identifier (table or column name).
public abstract string Quote(string identifier)
Parameters
identifierstring
Returns
RenameTableSql(string, string)
The DDL renaming a table. The target arrives unquoted because not every dialect renames with a statement — SQL Server calls a procedure, and its second argument is a bare name.
public virtual string RenameTableSql(string quotedTable, string target)
Parameters
Returns
SearchIndexSql(string, string, string)
The DDL materializing a model-declared search index (SearchIndex(...) / [SearchIndex])
on a text column, in execution order — empty when the dialect has no equivalent structure. The
declaration never changes semantics (LIKE pushes down regardless); it only changes the plan,
which is why a dialect without the structure ignores it instead of refusing.
public virtual IReadOnlyList<string> SearchIndexSql(string indexName, string quotedTable, string quotedColumn)
Parameters
indexNamestringThe unquoted index name (the dialect quotes it).
quotedTablestringThe quoted table.
quotedColumnstringThe quoted column.
Returns
SizedSqlType(Type, int, int, int)
The DDL type for a type with facets: varchar(n) for sized text, numeric(p,s) for sized
decimals, the plain SqlType(Type) otherwise. Dialects override the spellings.
public virtual string SizedSqlType(Type type, int length, int precision, int scale)
Parameters
typeTypeThe stored CLR type.
lengthintThe maximum text length (0 = default).
precisionintThe decimal precision (0 = default).
scaleintThe decimal scale.
Returns
SizedTextType(int)
The sized text type (varchar(n) by default).
protected virtual string SizedTextType(int length)
Parameters
lengthintThe maximum length.
Returns
SqlType(Type)
The DDL type for a CLR type (used by CREATE TABLE migrations).
public abstract string SqlType(Type type)
Parameters
typeType
Returns
SqlType(RelationalColumn)
The DDL type for a column, honouring its declared facets (text length, decimal precision/scale).
public string SqlType(RelationalColumn column)
Parameters
columnRelationalColumnThe column.
Returns
Synonym(string)
The one spelling this dialect uses for a type named without its facets.
protected virtual string Synonym(string baseType)
Parameters
baseTypestringThe lower-cased type name.
Returns
TableName(string)
Applies the naming convention to an entity name to produce its table name (snake_case by default).
public virtual string TableName(string entityName)
Parameters
entityNamestring
Returns
TupleComparison(IReadOnlyList<string>, ComparisonOperator, IReadOnlyList<string>)
Renders a row-wise tuple comparison; the base dialect cannot express it.
public virtual string TupleComparison(IReadOnlyList<string> columns, ComparisonOperator op, IReadOnlyList<string> parameters)
Parameters
columnsIReadOnlyList<string>The quoted columns.
opComparisonOperatorThe comparison operator.
parametersIReadOnlyList<string>The bound values' parameter markers.