Skip to content

Optimization: Dispatch Translator by virtual functions instead of switch statements #118

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 13 commits into from
Jan 2, 2024
36 changes: 8 additions & 28 deletions Orm/Xtensive.Orm.Firebird/Sql.Drivers.Firebird/v2_5/Translator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -231,34 +231,14 @@ public override void Translate(IOutput output, SqlDatePart datePart)
}
}

/// <inheritdoc/>
public override void Translate(SqlCompilerContext context, SqlSelect node, SelectSection section)
{
switch (section) {
case SelectSection.Limit:
_ = context.Output.Append("FIRST");
break;
case SelectSection.Offset:
_ = context.Output.Append("SKIP");
break;
default:
base.Translate(context, node, section);
break;
}
}
public override void SelectLimit(SqlCompilerContext context, SqlSelect node) =>
context.Output.AppendSpacePrefixed("FIRST ");

/// <inheritdoc/>
public override void Translate(SqlCompilerContext context, SqlUpdate node, UpdateSection section)
{
switch (section) {
case UpdateSection.Limit:
_ = context.Output.Append("ROWS");
break;
default:
base.Translate(context, node, section);
break;
}
}
public override void SelectOffset(SqlCompilerContext context, SqlSelect node) =>
context.Output.AppendSpacePrefixed("SKIP ");

public override void UpdateLimit(SqlCompilerContext context) =>
context.Output.AppendSpaceIfNecessary().Append("ROWS").AppendSpaceIfNecessary();

/// <inheritdoc />
public override void Translate(SqlCompilerContext context, SqlDelete node, DeleteSection section)
Expand Down Expand Up @@ -380,4 +360,4 @@ public Translator(SqlDriver driver)
DoubleFormatString = $"{base.DoubleFormatString}e0";
}
}
}
}
6 changes: 3 additions & 3 deletions Orm/Xtensive.Orm.MySql/Sql.Drivers.MySql/v5_0/Compiler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -258,15 +258,15 @@ public override void Visit(SqlPlaceholder node)
protected override void VisitSelectLimitOffset(SqlSelect node)
{
if (node.Limit is not null) {
AppendTranslated(node, SelectSection.Limit);
translator.SelectLimit(context, node);
node.Limit.AcceptVisitor(this);
}
if (node.Offset is not null) {
if (node.Limit is null) {
AppendTranslated(node, SelectSection.Limit);
translator.SelectLimit(context, node);
_ = context.Output.Append(" 18446744073709551615 "); // magic number from http://dev.mysql.com/doc/refman/5.0/en/select.html
}
AppendTranslated(node, SelectSection.Offset);
translator.SelectOffset(context, node);
node.Offset.AcceptVisitor(this);
}
}
Expand Down
50 changes: 17 additions & 33 deletions Orm/Xtensive.Orm.MySql/Sql.Drivers.MySql/v5_0/Translator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -63,34 +63,26 @@ protected override void TranslateChar(IOutput output, char ch)
}
}

/// <inheritdoc/>
public override void Translate(SqlCompilerContext context, SqlSelect node, SelectSection section)
public override void SelectHintsEntry(SqlCompilerContext context, SqlSelect node) { }

public override void SelectHintsExit(SqlCompilerContext context, SqlSelect node)
{
switch (section) {
case SelectSection.HintsEntry:
break;
case SelectSection.HintsExit:
if (node.Hints.Count == 0) {
break;
if (node.Hints.Count != 0) {
var hints = new List<string>(node.Hints.Count);
foreach (var hint in node.Hints) {
if (hint is SqlNativeHint sqlNativeHint) {
hints.Add(QuoteIdentifier(sqlNativeHint.HintText));
}
var hints = new List<string>(node.Hints.Count);
foreach (var hint in node.Hints) {
if (hint is SqlNativeHint sqlNativeHint) {
hints.Add(QuoteIdentifier(sqlNativeHint.HintText));
}
}
if (hints.Count > 0) {
_ = context.Output.Append("USE INDEX (")
.Append(string.Join(", ", hints))
.Append(")");
}
break;
default:
base.Translate(context, node, section);
break;
}
if (hints.Count > 0) {
_ = context.Output.Append("USE INDEX (")
.Append(string.Join(", ", hints))
.Append(")");
}
}
}


/// <inheritdoc/>
public override void Translate(IOutput output, SqlFunctionType type)
{
Expand Down Expand Up @@ -356,16 +348,8 @@ public override void Translate(SqlCompilerContext context, SqlAlterTable node, A
}
}

/// <inheritdoc/>
public override void Translate(SqlCompilerContext context, SqlInsert node, InsertSection section)
{
if (section == InsertSection.DefaultValues) {
_ = context.Output.Append("() VALUES ()");
}
else {
base.Translate(context, node, section);
}
}
public override void InsertDefaultValues(SqlCompilerContext context) =>
context.Output.AppendSpaceIfNecessary().AppendOpeningPunctuation("() VALUES ()");

/// <inheritdoc/>
public override void Translate(SqlCompilerContext context, SqlBreak node)
Expand Down
26 changes: 8 additions & 18 deletions Orm/Xtensive.Orm.Oracle/Sql.Drivers.Oracle/v09/Translator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -70,24 +70,14 @@ public override void TranslateString(IOutput output, string str)
base.TranslateString(output, str);
}

/// <inheritdoc/>
public override void Translate(SqlCompilerContext context, SqlSelect node, SelectSection section)
{
switch (section) {
case SelectSection.HintsEntry:
_ = context.Output.Append("/*+");
break;
case SelectSection.HintsExit:
_ = context.Output.Append("*/");
break;
case SelectSection.Limit:
case SelectSection.Offset:
throw new NotSupportedException();
default:
base.Translate(context, node, section);
break;
}
}
public override void SelectLimit(SqlCompilerContext context, SqlSelect node) => throw new NotSupportedException();
public override void SelectOffset(SqlCompilerContext context, SqlSelect node) => throw new NotSupportedException();

public override void SelectHintsEntry(SqlCompilerContext context, SqlSelect node) =>
context.Output.AppendSpacePrefixed("/*+ ");

public override void SelectHintsExit(SqlCompilerContext context, SqlSelect node) =>
context.Output.AppendSpacePrefixed("*/ ");

/// <inheritdoc/>
public override string Translate(SqlJoinMethod method)
Expand Down
9 changes: 2 additions & 7 deletions Orm/Xtensive.Orm.Oracle/Sql.Drivers.Oracle/v11/Translator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,8 @@ namespace Xtensive.Sql.Drivers.Oracle.v11
{
internal class Translator : v10.Translator
{
/// <inheritdoc/>
public override void Translate(SqlCompilerContext context, SqlOrder node, NodeSection section)
{
if (section == NodeSection.Exit) {
_ = context.Output.Append(node.Ascending ? "ASC NULLS FIRST" : "DESC NULLS LAST");
}
}
public override void OrderExit(SqlCompilerContext context, SqlOrder node) =>
context.Output.Append(node.Ascending ? "ASC NULLS FIRST" : "DESC NULLS LAST");

/// <inheritdoc/>
public override string Translate(SqlValueType type)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -453,23 +453,11 @@ public override void Translate(SqlCompilerContext context, SqlDeclareCursor node
}
}

/// <inheritdoc/>
public override void Translate(SqlCompilerContext context, SqlFetch node, FetchSection section)
{
switch (section) {
case FetchSection.Entry:
_ = context.Output.Append("FETCH ").Append(node.Option.ToString().ToUpper());
return;
case FetchSection.Targets:
var output = context.Output;
_ = output.Append("FROM ");
TranslateIdentifier(output, node.Cursor.Name);
return;
case FetchSection.Exit:
break;
}
base.Translate(context, node, section);
}
public override void FetchEntry(SqlCompilerContext context, SqlFetch node) =>
context.Output.Append("FETCH ").Append(node.Option.ToString().ToUpper());

public override void FetchTarget(SqlCompilerContext context, SqlFetch node) =>
TranslateIdentifier(context.Output.AppendSpaceIfNecessary().Append("FROM "), node.Cursor.Name);

/// <inheritdoc/>
public override void Translate(SqlCompilerContext context, SqlOpenCursor node)
Expand Down Expand Up @@ -962,4 +950,4 @@ public Translator(SqlDriver driver)
DoubleFormatString = base.DoubleFormatString + "'::float8'";
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,13 +44,8 @@ public override void Translate(SqlCompilerContext context, SqlCreateIndex node,
}
}

/// <inheritdoc/>
public override void Translate(SqlCompilerContext context, SqlOrder node, NodeSection section)
{
if (section == NodeSection.Exit) {
_ = context.Output.Append(node.Ascending ? "ASC NULLS FIRST" : "DESC NULLS LAST");
}
}
public override void OrderExit(SqlCompilerContext context, SqlOrder node) =>
context.Output.Append(node.Ascending ? "ASC NULLS FIRST" : "DESC NULLS LAST");

internal protected string GetFulltextVector(SqlCompilerContext context, FullTextIndex index)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ protected override void VisitUpdateLimit(SqlUpdate node)
throw new NotSupportedException(Strings.ExStorageDoesNotSupportLimitationOfRowCountToUpdate);
}

AppendTranslated(node, UpdateSection.Limit);
translator.UpdateLimit(context);
_ = context.Output.AppendOpeningPunctuation("(");
node.Limit.AcceptVisitor(this);
_ = context.Output.Append(")");
Expand Down
72 changes: 25 additions & 47 deletions Orm/Xtensive.Orm.SqlServer/Sql.Drivers.SqlServer/v09/Translator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -318,45 +318,32 @@ public override string Translate(SqlJoinMethod method)
};
}

/// <inheritdoc/>
public override void Translate(SqlCompilerContext context, SqlSelect node, SelectSection section)
public override void SelectLimit(SqlCompilerContext context, SqlSelect node) =>
context.Output.AppendSpacePrefixed("TOP ");

public override void SelectOffset(SqlCompilerContext context, SqlSelect node) => throw new NotSupportedException();

public override void SelectExit(SqlCompilerContext context, SqlSelect node)
{
var output = context.Output;
switch (section) {
case SelectSection.Entry:
base.Translate(context, node, section);
break;
case SelectSection.Limit:
_ = output.Append("TOP");
break;
case SelectSection.Offset:
throw new NotSupportedException();
case SelectSection.Exit:
var hasHints = false;
foreach (var hint in node.Hints) {
switch (hint) {
case SqlForceJoinOrderHint:
AppendHint(output, "FORCE ORDER", ref hasHints);
break;
case SqlFastFirstRowsHint sqlFastFirstRowsHint:
AppendHint(output, "FAST ", ref hasHints);
_ = output.Append(sqlFastFirstRowsHint.Amount);
break;
case SqlNativeHint sqlNativeHint:
AppendHint(output, sqlNativeHint.HintText, ref hasHints);
break;
}
}
if (hasHints) {
_ = output.Append(")");
}
break;
default:
base.Translate(context, node, section);
break;
var hasHints = false;
foreach (var hint in node.Hints) {
switch (hint) {
case SqlForceJoinOrderHint:
AppendHint(output, "FORCE ORDER", ref hasHints);
break;
case SqlFastFirstRowsHint sqlFastFirstRowsHint:
AppendHint(output, "FAST ", ref hasHints);
_ = output.Append(sqlFastFirstRowsHint.Amount);
break;
case SqlNativeHint sqlNativeHint:
AppendHint(output, sqlNativeHint.HintText, ref hasHints);
break;
}
}
if (hasHints) {
_ = output.Append(")");
}

/// <inheritdoc/>

static void AppendHint(IOutput output, string hint, ref bool hasHints)
{
Expand All @@ -371,17 +358,8 @@ static void AppendHint(IOutput output, string hint, ref bool hasHints)
}
}

public override void Translate(SqlCompilerContext context, SqlUpdate node, UpdateSection section)
{
switch (section) {
case UpdateSection.Limit:
_ = context.Output.Append("TOP");
break;
default:
base.Translate(context, node, section);
break;
}
}
public override void UpdateLimit(SqlCompilerContext context) =>
context.Output.AppendSpaceIfNecessary().Append("TOP").AppendSpaceIfNecessary();

/// <inheritdoc/>
public override void Translate(SqlCompilerContext context, SqlDelete node, DeleteSection section)
Expand Down
10 changes: 4 additions & 6 deletions Orm/Xtensive.Orm.SqlServer/Sql.Drivers.SqlServer/v11/Compiler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ protected override void VisitSelectLimitOffset(SqlSelect node)
return; // Nothing to process.
}

AppendTranslated(node, SelectSection.Offset);
translator.SelectOffset(context, node);

if (node.HasOffset) {
node.Offset.AcceptVisitor(this);
Expand All @@ -35,14 +35,12 @@ protected override void VisitSelectLimitOffset(SqlSelect node)
_ = context.Output.Append("0");
}

AppendSpaceIfNecessary();
translator.Translate(context, node, SelectSection.OffsetEnd);
translator.SelectOffsetEnd(context, node);

if (node.HasLimit) {
AppendTranslated(node, SelectSection.Limit);
translator.SelectLimit(context, node);
node.Limit.AcceptVisitor(this);
AppendSpaceIfNecessary();
translator.Translate(context, node, SelectSection.LimitEnd);
translator.SelectLimitEnd(context, node);
}
}

Expand Down
Loading