Engines

An engine contains the configuration of a specific SQL engine, and allows you to compile a query:

// Create your engine
IEngine engine = new Engine();

It accepts an ITableBuilder with the configuration of your tables:

// Create a table builder and add your entity classes
ITableBuilder tableBuilder = new TableBuilder();
tableBuilder.Add<Person>();
tableBuilder.Add<Department>();

// Create an engine with the table builder
IEngine engine = new Engine(tableBuilder);

You can have any number of engines. The engines can share the same ITableBuilder or have his own ITableBuilder with different configuration.

Supported engines

You can use Suilder with any SQL engine, but there a list of supported engines that are already configured.

Engine Class name Remarks
MySQL MySQLEngine
Oracle Database OracleDBEngine By default it uses quoted uppercase names.
PostgreSQL PostgreSQLEngine By default it uses quoted lowercase names.
SQLite SQLiteEngine
SQL Server SQLServerEngine

If your SQL engine is not in the list, it does not mean that you cannot use Suilder with them, but you have to configure your engine.

Engine configuration

You can change the configuration of the engine using the Options property:

IEngine engine = new Engine();
engine.Options.EscapeStart = '[';
engine.Options.EscapeEnd = ']';
engine.Options.Pagination = PaginationStyle.Offset;

Warning

If you need different configurations, you must create multiple engines instances, modify the configuration continuously before execute a query is not thread safe.

You can inherit the Engine class instead and override the InitOptions method:

protected override EngineOptions InitOptions()
{
    EngineOptions options = new EngineOptions();
    options.EscapeStart = '[';
    options.EscapeEnd = ']';
    options.Pagination = PaginationStyle.Offset;

    return options;
}

You can alter the following configurations:

Property Default value Description
Name null The engine name.
EscapeStart " The start character to delimit identifiers.
EscapeEnd " The end character to delimit identifiers.
UpperCaseNames false If true, converts all tables and column names to uppercase.
LowerCaseNames false If true, converts all tables and column names to lowercase.
TableAs true If true, adds the "as" keyword before the alias of a table.
FromDummyName null The name of a dummy table for engines that always need a "from" clause. Set to null for engines that do not need a dummy table.
WithRecursive false If the "with" clause needs the "recursive" keyword.
TopSupported true If the engine supports "top".
TopAsParameters true If true, adds the top values as parameters.
DistinctOnSupported true If the engine supports "distinct on".
RightJoinSupported true If the engine supports "right join".
FullJoinSupported true If the engine supports "full join".
OffsetStyle OffsetStyle.Offset The offset style.
OffsetAsParameters true If true, adds the offset values as parameters.
InsertWithUnion false If the "insert" statement must use a "select union all" to insert multiple rows.
UpdateWithFrom false If the "update" statement must have a "from" clause. Some engines need it when the table has an alias or a join.
UpdateSetWithTableName false If the column must have the table name in the "set" clause. Some engines need it when the table has a join.
DeleteWithAlias true If the "delete" statement must have an alias before the "from" clause. Some engines need it when the table has an alias or a join.
SetOperatorWrapQuery true If true, adds parentheses to the set operator queries.
SetOperatorWithSubQuery false If the set operator must use a subquery when the value is another set operator.
ParameterPrefix "@p" The prefix of the parameters.
ParameterIndex true If true, adds the index after the parameter name.
FunctionsOnlyRegistered false If only allow registered functions.

Register operators

You can register operators with the AddOperator method to translate them with a different name:

// Translate 'EXCEPT' to 'MINUS'
engine.AddOperator("EXCEPT", "MINUS");

You can also translate the operator into a function:

// Translate '&' to 'BITAND()'
engine.AddOperator("&", "BITAND", true);

Register functions

You can register functions with the AddFunction method to translate them with a different name:

// Translate 'LENGTH' to 'LEN'
engine.AddFunction("LENGTH", "LEN");

You can also add a delegate to compile the function to SQL:

engine.AddFunction("CAST", (queryBuilder, engine, name, fn) =>
{
    queryBuilder.Write(name + "(");
    queryBuilder.WriteValue(fn.Args[0]);
    queryBuilder.Write(" AS ");
    queryBuilder.WriteValue(fn.Args[1]);
    queryBuilder.Write(")");
});

Note

The delegate function works like the Compile method of the IQueryFragment interface.

You can inherit the Engine class instead and override the InitFunctions method.

protected override void InitFunctions()
{
    // Translate 'LENGTH' to 'LEN'
    engine.AddFunction("LENGTH", "LEN");
}

The supported engines has already registered the functions of the SqlFn and SqlExp classes.

Compile the query

The engine can compile any object that implements the IQueryFragment interface.

// Create your query
IAlias person = sql.Alias("person");
IQueryFragment query = sql.Query
    .Select(person.All)
    .From(person)
    .Where(person["Id"].Eq(1));

// Compile the query using the engine
QueryResult result = engine.Compile(query);

// This is the SQL result:
// SELECT "person".* FROM "person" WHERE "person"."Id" = @p0
result.Sql;

// This is a dictionary with the parameters:
// { ["@p0"] = 1 }
result.Parameters;

Parameters

The default parameter name is @p or :p (Oracle), but you can set any name:

// Change parameter prefix
engine.Options.ParameterPrefix = "$p";

You can also remove the index from the parameter name to use positional parameters:

// Enable positional parameters
engine.Options.ParameterPrefix = "?";
engine.Options.ParameterIndex = false;

The parameters will be added to a list instead of a dictionary:

// This is the SQL result:
// SELECT "person".* FROM "person" WHERE "person"."Id" = ?
result.Sql;

// This is a list with the parameters:
// { 1 }
result.ParametersList;