From 378387537c9dbef9ddf985c55eadc78f3833d383 Mon Sep 17 00:00:00 2001 From: Sergei Pavlov Date: Tue, 2 Jan 2024 15:45:23 -0800 Subject: [PATCH] Optimization: Dispatch Translator by virtual functions instead of switch statements (#118) * Optimization: Dispatch Translator by virtual functions instead of switch statements * AppendSpacePrefixed() helper * Refactor ColumnSection * virtual JoinCondition() * Eliminate IfSection * Eliminate InsertSection * LikeSection * BetweenSection * FetchSection * WhileSection * SqlOrder * UpdateSection --- .../Sql.Drivers.Firebird/v2_5/Translator.cs | 36 +- .../Sql.Drivers.MySql/v5_0/Compiler.cs | 8 +- .../Sql.Drivers.MySql/v5_0/Translator.cs | 50 +-- .../Sql.Drivers.Oracle/v09/Translator.cs | 26 +- .../Sql.Drivers.Oracle/v11/Translator.cs | 9 +- .../Sql.Drivers.PostgreSql/v8_0/Translator.cs | 22 +- .../Sql.Drivers.PostgreSql/v8_3/Translator.cs | 9 +- .../Sql.Drivers.SqlServer/v09/Compiler.cs | 2 +- .../Sql.Drivers.SqlServer/v09/Translator.cs | 79 ++-- .../Sql.Drivers.SqlServer/v11/Compiler.cs | 10 +- .../Sql.Drivers.SqlServer/v11/Translator.cs | 33 +- .../Sql.Drivers.Sqlite/v3/Compiler.cs | 8 +- .../Sql.Drivers.Sqlite/v3/Translator.cs | 22 +- .../Compiler/Internals/Nodes/ContainerNode.cs | 3 + Orm/Xtensive.Orm/Sql/Compiler/SqlCompiler.cs | 212 +++-------- .../Sql/Compiler/SqlNodeSections.cs | 85 ----- .../Sql/Compiler/SqlTranslator.cs | 338 ++++++++---------- 17 files changed, 306 insertions(+), 646 deletions(-) diff --git a/Orm/Xtensive.Orm.Firebird/Sql.Drivers.Firebird/v2_5/Translator.cs b/Orm/Xtensive.Orm.Firebird/Sql.Drivers.Firebird/v2_5/Translator.cs index 9e6d9b16c3..44fb681b25 100644 --- a/Orm/Xtensive.Orm.Firebird/Sql.Drivers.Firebird/v2_5/Translator.cs +++ b/Orm/Xtensive.Orm.Firebird/Sql.Drivers.Firebird/v2_5/Translator.cs @@ -231,34 +231,14 @@ public override void Translate(IOutput output, SqlDatePart datePart) } } - /// - 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 "); - /// - 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(); /// public override void Translate(SqlCompilerContext context, SqlDelete node, DeleteSection section) @@ -380,4 +360,4 @@ public Translator(SqlDriver driver) DoubleFormatString = $"{base.DoubleFormatString}e0"; } } -} +} \ No newline at end of file diff --git a/Orm/Xtensive.Orm.MySql/Sql.Drivers.MySql/v5_0/Compiler.cs b/Orm/Xtensive.Orm.MySql/Sql.Drivers.MySql/v5_0/Compiler.cs index 0a66284582..f3e5e3acee 100644 --- a/Orm/Xtensive.Orm.MySql/Sql.Drivers.MySql/v5_0/Compiler.cs +++ b/Orm/Xtensive.Orm.MySql/Sql.Drivers.MySql/v5_0/Compiler.cs @@ -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); } } @@ -437,7 +437,7 @@ protected static SqlUserFunctionCall BitNot(SqlExpression operand) => SqlDml.RawConcat( operand, SqlDml.Native("AS SIGNED")))); - + #endregion diff --git a/Orm/Xtensive.Orm.MySql/Sql.Drivers.MySql/v5_0/Translator.cs b/Orm/Xtensive.Orm.MySql/Sql.Drivers.MySql/v5_0/Translator.cs index 8675b2e563..8ae3ce5ead 100644 --- a/Orm/Xtensive.Orm.MySql/Sql.Drivers.MySql/v5_0/Translator.cs +++ b/Orm/Xtensive.Orm.MySql/Sql.Drivers.MySql/v5_0/Translator.cs @@ -63,34 +63,26 @@ protected override void TranslateChar(IOutput output, char ch) } } - /// - 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(node.Hints.Count); + foreach (var hint in node.Hints) { + if (hint is SqlNativeHint sqlNativeHint) { + hints.Add(QuoteIdentifier(sqlNativeHint.HintText)); } - var hints = new List(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(")"); + } } } + /// public override void Translate(IOutput output, SqlFunctionType type) { @@ -356,16 +348,8 @@ public override void Translate(SqlCompilerContext context, SqlAlterTable node, A } } - /// - 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 ()"); /// public override void Translate(SqlCompilerContext context, SqlBreak node) diff --git a/Orm/Xtensive.Orm.Oracle/Sql.Drivers.Oracle/v09/Translator.cs b/Orm/Xtensive.Orm.Oracle/Sql.Drivers.Oracle/v09/Translator.cs index 25bc665d52..764a69789c 100644 --- a/Orm/Xtensive.Orm.Oracle/Sql.Drivers.Oracle/v09/Translator.cs +++ b/Orm/Xtensive.Orm.Oracle/Sql.Drivers.Oracle/v09/Translator.cs @@ -70,24 +70,14 @@ public override void TranslateString(IOutput output, string str) base.TranslateString(output, str); } - /// - 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("*/ "); /// public override string Translate(SqlJoinMethod method) diff --git a/Orm/Xtensive.Orm.Oracle/Sql.Drivers.Oracle/v11/Translator.cs b/Orm/Xtensive.Orm.Oracle/Sql.Drivers.Oracle/v11/Translator.cs index 67c9a80be7..65e54d6a66 100644 --- a/Orm/Xtensive.Orm.Oracle/Sql.Drivers.Oracle/v11/Translator.cs +++ b/Orm/Xtensive.Orm.Oracle/Sql.Drivers.Oracle/v11/Translator.cs @@ -13,13 +13,8 @@ namespace Xtensive.Sql.Drivers.Oracle.v11 { internal class Translator : v10.Translator { - /// - 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"); /// public override string Translate(SqlValueType type) diff --git a/Orm/Xtensive.Orm.PostgreSql/Sql.Drivers.PostgreSql/v8_0/Translator.cs b/Orm/Xtensive.Orm.PostgreSql/Sql.Drivers.PostgreSql/v8_0/Translator.cs index 322509933e..c1c8b3c7dd 100644 --- a/Orm/Xtensive.Orm.PostgreSql/Sql.Drivers.PostgreSql/v8_0/Translator.cs +++ b/Orm/Xtensive.Orm.PostgreSql/Sql.Drivers.PostgreSql/v8_0/Translator.cs @@ -453,23 +453,11 @@ public override void Translate(SqlCompilerContext context, SqlDeclareCursor node } } - /// - 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); /// public override void Translate(SqlCompilerContext context, SqlOpenCursor node) diff --git a/Orm/Xtensive.Orm.PostgreSql/Sql.Drivers.PostgreSql/v8_3/Translator.cs b/Orm/Xtensive.Orm.PostgreSql/Sql.Drivers.PostgreSql/v8_3/Translator.cs index fb0fe8279e..86c665a07c 100644 --- a/Orm/Xtensive.Orm.PostgreSql/Sql.Drivers.PostgreSql/v8_3/Translator.cs +++ b/Orm/Xtensive.Orm.PostgreSql/Sql.Drivers.PostgreSql/v8_3/Translator.cs @@ -44,13 +44,8 @@ public override void Translate(SqlCompilerContext context, SqlCreateIndex node, } } - /// - 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) { diff --git a/Orm/Xtensive.Orm.SqlServer/Sql.Drivers.SqlServer/v09/Compiler.cs b/Orm/Xtensive.Orm.SqlServer/Sql.Drivers.SqlServer/v09/Compiler.cs index 7c56b6b41b..fca312393c 100644 --- a/Orm/Xtensive.Orm.SqlServer/Sql.Drivers.SqlServer/v09/Compiler.cs +++ b/Orm/Xtensive.Orm.SqlServer/Sql.Drivers.SqlServer/v09/Compiler.cs @@ -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(")"); diff --git a/Orm/Xtensive.Orm.SqlServer/Sql.Drivers.SqlServer/v09/Translator.cs b/Orm/Xtensive.Orm.SqlServer/Sql.Drivers.SqlServer/v09/Translator.cs index 7f07342b1c..e86eb7ca29 100644 --- a/Orm/Xtensive.Orm.SqlServer/Sql.Drivers.SqlServer/v09/Translator.cs +++ b/Orm/Xtensive.Orm.SqlServer/Sql.Drivers.SqlServer/v09/Translator.cs @@ -314,42 +314,31 @@ public override string Translate(SqlJoinMethod method) }; } - /// - 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(")"); } static void AppendHint(IOutput output, string hint, ref bool hasHints) @@ -365,18 +354,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(); /// public override void Translate(SqlCompilerContext context, SqlDelete node, DeleteSection section) @@ -677,19 +656,19 @@ protected virtual string GetCurentNameOfDefaultConstraintScript() { return @"DECLARE @{0} VARCHAR(256) SELECT @{0} = {1}.sys.default_constraints.name - FROM + FROM {1}.sys.all_columns INNER JOIN {1}.sys.tables ON all_columns.object_id = tables.object_id - INNER JOIN + INNER JOIN {1}.sys.schemas - ON tables.schema_id = schemas.schema_id + ON tables.schema_id = schemas.schema_id INNER JOIN {1}.sys.default_constraints ON all_columns.default_object_id = default_constraints.object_id - WHERE + WHERE schemas.name = '{2}' AND tables.name = '{3}' AND all_columns.name = '{4}'"; diff --git a/Orm/Xtensive.Orm.SqlServer/Sql.Drivers.SqlServer/v11/Compiler.cs b/Orm/Xtensive.Orm.SqlServer/Sql.Drivers.SqlServer/v11/Compiler.cs index b4f91e357b..662f2396bf 100644 --- a/Orm/Xtensive.Orm.SqlServer/Sql.Drivers.SqlServer/v11/Compiler.cs +++ b/Orm/Xtensive.Orm.SqlServer/Sql.Drivers.SqlServer/v11/Compiler.cs @@ -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); @@ -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); } } diff --git a/Orm/Xtensive.Orm.SqlServer/Sql.Drivers.SqlServer/v11/Translator.cs b/Orm/Xtensive.Orm.SqlServer/Sql.Drivers.SqlServer/v11/Translator.cs index f9fddc03c4..9c5933bf14 100644 --- a/Orm/Xtensive.Orm.SqlServer/Sql.Drivers.SqlServer/v11/Translator.cs +++ b/Orm/Xtensive.Orm.SqlServer/Sql.Drivers.SqlServer/v11/Translator.cs @@ -50,28 +50,17 @@ public override void Translate(SqlCompilerContext context, SequenceDescriptor de } } - /// - public override void Translate(SqlCompilerContext context, SqlSelect node, SelectSection section) - { - var output = context.Output; - switch (section) { - case SelectSection.Limit: - _ = output.Append("FETCH NEXT"); - break; - case SelectSection.LimitEnd: - _ = output.Append("ROWS ONLY"); - break; - case SelectSection.Offset: - _ = output.Append("OFFSET"); - break; - case SelectSection.OffsetEnd: - _ = output.Append("ROWS"); - break; - default: - base.Translate(context, node, section); - break; - } - } + public override void SelectLimit(SqlCompilerContext context, SqlSelect node) => + context.Output.AppendSpacePrefixed("FETCH NEXT "); + + public override void SelectOffset(SqlCompilerContext context, SqlSelect node) => + context.Output.AppendSpacePrefixed("OFFSET "); + + public override void SelectLimitEnd(SqlCompilerContext context, SqlSelect node) => + context.Output.AppendSpacePrefixed("ROWS ONLY "); + + public override void SelectOffsetEnd(SqlCompilerContext context, SqlSelect node) => + context.Output.AppendSpacePrefixed("ROWS "); private void TranslateSequenceStatement(SqlCompilerContext context, Sequence sequence, string action) { diff --git a/Orm/Xtensive.Orm.Sqlite/Sql.Drivers.Sqlite/v3/Compiler.cs b/Orm/Xtensive.Orm.Sqlite/Sql.Drivers.Sqlite/v3/Compiler.cs index dc044373f7..68a53377d3 100644 --- a/Orm/Xtensive.Orm.Sqlite/Sql.Drivers.Sqlite/v3/Compiler.cs +++ b/Orm/Xtensive.Orm.Sqlite/Sql.Drivers.Sqlite/v3/Compiler.cs @@ -351,13 +351,13 @@ protected override void VisitSelectLimitOffset(SqlSelect node) return; } - AppendTranslated(node, SelectSection.Limit); + translator.SelectLimit(context, node); SqlDml.Literal(-1).AcceptVisitor(this); - AppendTranslated(node, SelectSection.LimitEnd); + translator.SelectLimitEnd(context, node); - AppendTranslated(node, SelectSection.Offset); + translator.SelectOffset(context, node); node.Offset.AcceptVisitor(this); - AppendTranslated(node, SelectSection.OffsetEnd); + translator.SelectOffsetEnd(context, node); } /// diff --git a/Orm/Xtensive.Orm.Sqlite/Sql.Drivers.Sqlite/v3/Translator.cs b/Orm/Xtensive.Orm.Sqlite/Sql.Drivers.Sqlite/v3/Translator.cs index de11b35025..34a77d17a6 100644 --- a/Orm/Xtensive.Orm.Sqlite/Sql.Drivers.Sqlite/v3/Translator.cs +++ b/Orm/Xtensive.Orm.Sqlite/Sql.Drivers.Sqlite/v3/Translator.cs @@ -274,17 +274,17 @@ public override void Translate(SqlCompilerContext context, SqlFunctionCall node, } } - /// - public override void Translate(SqlCompilerContext context, SqlUpdate node, UpdateSection section) - { - _ = context.Output.Append(section switch { - UpdateSection.Entry => "UPDATE", - UpdateSection.Set => "SET", - UpdateSection.From => "FROM", - UpdateSection.Where => "WHERE", - _ => string.Empty - }); - } + public override void UpdateSet(SqlCompilerContext context) => + context.Output.AppendSpaceIfNecessary().Append("SET").AppendSpaceIfNecessary(); + + public override void UpdateFrom(SqlCompilerContext context) => + context.Output.AppendSpaceIfNecessary().Append("FROM").AppendSpaceIfNecessary(); + + public override void UpdateWhere(SqlCompilerContext context, SqlUpdate node) => + context.Output.AppendSpaceIfNecessary().Append("WHERE").AppendSpaceIfNecessary(); + + public override void UpdateLimit(SqlCompilerContext context) => + context.Output.AppendSpaceIfNecessary(); /// public override void Translate(SqlCompilerContext context, SqlCreateIndex node, CreateIndexSection section) diff --git a/Orm/Xtensive.Orm/Sql/Compiler/Internals/Nodes/ContainerNode.cs b/Orm/Xtensive.Orm/Sql/Compiler/Internals/Nodes/ContainerNode.cs index afb1f1a8ab..051a288664 100644 --- a/Orm/Xtensive.Orm/Sql/Compiler/Internals/Nodes/ContainerNode.cs +++ b/Orm/Xtensive.Orm/Sql/Compiler/Internals/Nodes/ContainerNode.cs @@ -273,6 +273,9 @@ public IOutput AppendSpaceIfNecessary() return AppendSpace(); } + public IOutput AppendSpacePrefixed(string text) => + AppendSpaceIfNecessary().Append(text); + /// public IOutput AppendNewLine(string text) { diff --git a/Orm/Xtensive.Orm/Sql/Compiler/SqlCompiler.cs b/Orm/Xtensive.Orm/Sql/Compiler/SqlCompiler.cs index 4e9f32eb6a..9e70e11c91 100644 --- a/Orm/Xtensive.Orm/Sql/Compiler/SqlCompiler.cs +++ b/Orm/Xtensive.Orm/Sql/Compiler/SqlCompiler.cs @@ -305,13 +305,11 @@ public virtual void Visit(SqlBatch node) public virtual void Visit(SqlBetween node) { using (context.EnterScope(node)) { - AppendTranslatedEntry(node); node.Expression.AcceptVisitor(this); - AppendTranslated(node, BetweenSection.Between); + translator.BetweenBetween(context, node); node.Left.AcceptVisitor(this); - AppendTranslated(node, BetweenSection.And); + translator.BetweenAnd(context, node); node.Right.AcceptVisitor(this); - AppendTranslatedExit(node); } } @@ -441,7 +439,8 @@ public virtual void Visit(SqlCollate node) /// Visits and translates its parts. /// /// Column reference to visit. - public virtual void Visit(SqlColumnRef node) => AppendTranslated(node, ColumnSection.Entry); + public virtual void Visit(SqlColumnRef node) => + translator.ColumnEntry(context, node); /// /// Visits table and translates its parts. @@ -1151,15 +1150,14 @@ public virtual void Visit(SqlDynamicFilter node) public virtual void Visit(SqlFetch node) { using (context.EnterScope(node)) { - AppendTranslatedEntry(node); + translator.FetchEntry(context, node); if (node.RowCount is not null) { node.RowCount.AcceptVisitor(this); } - AppendTranslated(node, FetchSection.Targets); + translator.FetchTarget(context, node); foreach (var item in node.Targets) { item.AcceptVisitor(this); } - AppendTranslatedExit(node); } } @@ -1220,19 +1218,19 @@ public virtual void Visit(SqlCustomFunctionCall node) => public virtual void Visit(SqlIf node) { using (context.EnterScope(node)) { - AppendTranslated(node, IfSection.Entry); + translator.IfEntry(context); node.Condition.AcceptVisitor(this); - AppendTranslated(node, IfSection.True); + translator.IfTrue(context); node.True.AcceptVisitor(this); if (node.False != null) { - AppendTranslated(node, IfSection.False); + translator.IfFalse(context); node.False.AcceptVisitor(this); } - AppendTranslated(node, IfSection.Exit); + translator.IfExit(context); } } @@ -1243,7 +1241,8 @@ public virtual void Visit(SqlIf node) public virtual void Visit(SqlInsert node) { using (context.EnterScope(node)) { - AppendTranslatedEntry(node); + translator.InsertEntry(context); + AppendSpaceIfNecessary(); if (node.Into == null) { throw new SqlCompilerException(Strings.ExTablePropertyIsNotSet); @@ -1253,7 +1252,7 @@ public virtual void Visit(SqlInsert node) node.Into.AcceptVisitor(this); } - AppendTranslated(node, InsertSection.ColumnsEntry); + translator.InsertColumnsEntry(context, node); var columns = node.ValueRows.Columns; if (columns.Count > 0) { using (context.EnterCollectionScope()) { @@ -1264,9 +1263,9 @@ public virtual void Visit(SqlInsert node) } } - AppendTranslated(node, InsertSection.ColumnsExit); + translator.InsertColumnsExit(context, node); if (node.ValueRows.Count == 0 && node.From == null) { - AppendTranslated(node, InsertSection.DefaultValues); + translator.InsertDefaultValues(context); } else { if (node.From != null) { @@ -1275,7 +1274,7 @@ public virtual void Visit(SqlInsert node) } } else { - AppendTranslated(node, InsertSection.ValuesEntry); + translator.InsertValuesEntry(context, node); bool firstRow = true; foreach (var row in node.ValueRows) { if (!firstRow) { @@ -1285,10 +1284,10 @@ public virtual void Visit(SqlInsert node) firstRow = false; row.AcceptVisitor(this); } - AppendTranslated(node, InsertSection.ValuesExit); + translator.InsertValuesExit(context, node); } } - AppendTranslatedExit(node); + translator.InsertExit(context); } } @@ -1310,7 +1309,7 @@ public virtual void Visit(SqlJoinExpression node) AppendTranslated(node, JoinSection.Specification); node.Right.AcceptVisitor(this); if (node.Expression is not null) { - AppendTranslated(node, JoinSection.Condition); + translator.JoinCondition(context, node); node.Expression.AcceptVisitor(this); } AppendTranslated(node, JoinSection.Exit); @@ -1333,15 +1332,15 @@ public virtual void Visit(SqlJoinHint node) public virtual void Visit(SqlLike node) { using (context.EnterScope(node)) { - AppendTranslatedEntry(node); + translator.LikeEntry(context); node.Expression.AcceptVisitor(this); - AppendTranslated(node, LikeSection.Like); + translator.LikeLike(context, node); node.Pattern.AcceptVisitor(this); if (node.Escape is not null) { - AppendTranslated(node, LikeSection.Escape); + translator.LikeEscape(context); node.Escape.AcceptVisitor(this); } - AppendTranslatedExit(node); + translator.LikeExit(context); } } @@ -1397,7 +1396,6 @@ public virtual void Visit(SqlOrder node) { using (context.EnterScope(node)) { AppendSpaceIfNecessary(); - translator.Translate(context, node, NodeSection.Entry); if (node.Expression is not null) { node.Expression.AcceptVisitor(this); } @@ -1405,7 +1403,7 @@ public virtual void Visit(SqlOrder node) _ = context.Output.Append(node.Position.ToString()); } AppendSpace(); - translator.Translate(context, node, NodeSection.Exit); + translator.OrderExit(context, node); } } @@ -1570,13 +1568,13 @@ protected virtual void VisitSelectHints(SqlSelect node) } using (context.EnterCollectionScope()) { - AppendTranslated(node, SelectSection.HintsEntry); + translator.SelectHintsEntry(context, node); hints[0].AcceptVisitor(this); for (var i = 1; i < hints.Count; i++) { AppendDelimiter(translator.HintDelimiter); hints[i].AcceptVisitor(this); } - AppendTranslated(node, SelectSection.HintsExit); + translator.SelectHintsExit(context, node); } } @@ -1599,7 +1597,7 @@ protected virtual void VisitSelectColumns(SqlSelect node) } var cr = item as SqlColumnRef; - if (cr is not null && cr.SqlColumn is SqlColumnStub) { + if (cr?.SqlColumn is SqlColumnStub) { continue; } @@ -1607,7 +1605,7 @@ protected virtual void VisitSelectColumns(SqlSelect node) if (cr is not null) { AppendSpaceIfNecessary(); cr.SqlColumn.AcceptVisitor(this); - translator.Translate(context, cr, ColumnSection.AliasDeclaration); + translator.ColumnAliasDeclaration(context, cr); } else { AppendSpaceIfNecessary(); @@ -1628,8 +1626,7 @@ protected virtual void VisitSelectFrom(SqlSelect node) } AppendSpace(); - translator.Translate(context, node, SelectSection.From); - AppendSpace(); + translator.SelectFrom(context, node); var joinedFrom = node.From as SqlJoinedTable; var linearJoinRequired = CheckFeature(QueryFeatures.StrictJoinSyntax) && joinedFrom != null; @@ -1652,7 +1649,7 @@ protected virtual void VisitSelectFrom(SqlSelect node) AppendTranslated(join, JoinSection.Specification); table.AcceptVisitor(this); if (condition is not null) { - AppendTranslated(join, JoinSection.Condition); + translator.JoinCondition(context, join); condition.AcceptVisitor(this); } @@ -1670,7 +1667,7 @@ protected virtual void VisitSelectWhere(SqlSelect node) return; } - AppendTranslated(node, SelectSection.Where); + translator.SelectWhere(context, node); node.Where.AcceptVisitor(this); } @@ -1684,9 +1681,7 @@ protected virtual void VisitSelectGroupBy(SqlSelect node) return; } // group by - AppendSpace(); - translator.Translate(context, node, SelectSection.GroupBy); - AppendSpace(); + translator.SelectGroupBy(context, node); using (context.EnterCollectionScope()) { foreach (var item in node.GroupBy) { AppendCollectionDelimiterIfNecessary(AppendColumnDelimiter); @@ -1703,7 +1698,7 @@ protected virtual void VisitSelectGroupBy(SqlSelect node) return; } // having - AppendTranslated(node, SelectSection.Having); + translator.SelectHaving(context, node); node.Having.AcceptVisitor(this); } @@ -1717,9 +1712,7 @@ protected virtual void VisitSelectOrderBy(SqlSelect node) return; } - AppendSpace(); - translator.Translate(context, node, SelectSection.OrderBy); - AppendSpace(); + translator.SelectOrderBy(context, node); using (context.EnterCollectionScope()) { foreach (var item in node.OrderBy) { AppendCollectionDelimiterIfNecessary(AppendColumnDelimiter); @@ -1735,14 +1728,14 @@ protected virtual void VisitSelectOrderBy(SqlSelect node) protected virtual void VisitSelectLimitOffset(SqlSelect node) { if (node.Limit is not null) { - AppendTranslated(node, SelectSection.Limit); + translator.SelectLimit(context, node); node.Limit.AcceptVisitor(this); - AppendTranslated(node, SelectSection.LimitEnd); + translator.SelectLimitEnd(context, node); } if (node.Offset is not null) { - AppendTranslated(node, SelectSection.Offset); + translator.SelectOffset(context, node); node.Offset.AcceptVisitor(this); - AppendTranslated(node, SelectSection.OffsetEnd); + translator.SelectOffsetEnd(context, node); } } @@ -1871,7 +1864,8 @@ protected void VisitUpdateDefault(SqlUpdate node) /// Visits entry part of statement. /// /// Statement to visit. - protected virtual void VisitUpdateEntry(SqlUpdate node) => AppendTranslatedEntry(node); + protected virtual void VisitUpdateEntry(SqlUpdate node) => + translator.UpdateEntry(context, node); /// /// Visits UPDATE part of statement. @@ -1894,7 +1888,7 @@ protected virtual void VisitUpdateUpdate(SqlUpdate node) /// Statement to visit. protected virtual void VisitUpdateSet(SqlUpdate node) { - AppendTranslated(node, UpdateSection.Set); + translator.UpdateSet(context); using (context.EnterCollectionScope()) { foreach (var item in node.Values.Keys) { @@ -1917,7 +1911,7 @@ protected virtual void VisitUpdateSet(SqlUpdate node) protected virtual void VisitUpdateFrom(SqlUpdate node) { if (Driver.ServerInfo.Query.Features.Supports(QueryFeatures.UpdateFrom) && node.From != null) { - AppendTranslated(node, UpdateSection.From); + translator.UpdateFrom(context); node.From.AcceptVisitor(this); } } @@ -1929,7 +1923,7 @@ protected virtual void VisitUpdateFrom(SqlUpdate node) protected virtual void VisitUpdateWhere(SqlUpdate node) { if (node.Where is not null) { - AppendTranslated(node, UpdateSection.Where); + translator.UpdateWhere(context, node); node.Where.AcceptVisitor(this); } } @@ -1945,7 +1939,7 @@ protected virtual void VisitUpdateLimit(SqlUpdate node) throw new NotSupportedException(Strings.ExStorageIsNotSupportedLimitationOfRowCountToUpdate); } - AppendTranslated(node, UpdateSection.Limit); + translator.UpdateLimit(context); node.Limit.AcceptVisitor(this); } } @@ -1954,7 +1948,9 @@ protected virtual void VisitUpdateLimit(SqlUpdate node) /// Visits end part of statement. /// /// Statement to visit. - protected virtual void VisitUpdateExit(SqlUpdate node) => AppendTranslatedExit(node); + protected virtual void VisitUpdateExit(SqlUpdate node) + { + } /// /// Visits expression. @@ -2029,11 +2025,11 @@ public virtual void Visit(SqlVariant node) public virtual void Visit(SqlWhile node) { using (context.EnterScope(node)) { - AppendTranslated(node, WhileSection.Entry); + translator.WhileEntry(context); node.Condition.AcceptVisitor(this); - AppendTranslated(node, WhileSection.Statement); + translator.WhileStatement(context); node.Statement.AcceptVisitor(this); - AppendTranslated(node, WhileSection.Exit); + translator.WhileExit(context); } } @@ -2288,22 +2284,6 @@ protected void AppendTranslated(SqlArray node, ArraySection section) translator.Translate(context, node, section); } - protected void AppendTranslated(SqlBetween node, BetweenSection section) - { - AppendSpaceIfNecessary(); - translator.Translate(context, node, section); - AppendSpaceIfNecessary(); - } - - protected void AppendTranslatedEntry(SqlBetween node) - { - AppendSpaceIfNecessary(); - translator.Translate(context, node, BetweenSection.Entry); - } - - protected void AppendTranslatedExit(SqlBetween node) => - translator.Translate(context, node, BetweenSection.Exit); - protected void AppendTranslatedEntry(SqlBinary node) { AppendSpaceIfNecessary(); @@ -2392,13 +2372,6 @@ protected void AppendTranslated(SqlCollate node, NodeSection section) translator.Translate(context, node, section); } - protected void AppendTranslated(SqlColumnRef node, ColumnSection section) - { - AppendSpaceIfNecessary(); - translator.Translate(context, node, section); - AppendSpaceIfNecessary(); - } - protected void AppendTranslatedEntry(SqlConcat node) { AppendSpaceIfNecessary(); @@ -2576,18 +2549,6 @@ protected void AppendTranslatedEntry(SqlDelete node) protected void AppendTranslatedExit(SqlDelete node) => translator.Translate(context, node, DeleteSection.Exit); - protected void AppendTranslated(SqlFetch node, FetchSection section) - { - AppendSpaceIfNecessary(); - translator.Translate(context, node, section); - } - - protected void AppendTranslatedEntry(SqlFetch node) => - translator.Translate(context, node, FetchSection.Entry); - - protected void AppendTranslatedExit(SqlFetch node) => - translator.Translate(context, node, FetchSection.Exit); - protected void AppendTranslated(SqlFunctionCall node, FunctionCallSection section, int position) { AppendSpaceIfNecessary(); @@ -2618,49 +2579,12 @@ protected void AppendTranslatedEntry(SqlUserFunctionCall node) protected void AppendTranslatedExit(SqlUserFunctionCall node) => translator.Translate(context, node, FunctionCallSection.Exit, -1); - protected void AppendTranslated(SqlIf node, IfSection section) - { - AppendSpaceIfNecessary(); - translator.Translate(context, node, section); - } - - protected void AppendTranslated(SqlInsert node, InsertSection section) - { - AppendSpaceIfNecessary(); - translator.Translate(context, node, section); - } - - protected void AppendTranslatedEntry(SqlInsert node) - { - translator.Translate(context, node, InsertSection.Entry); - AppendSpaceIfNecessary(); - } - - protected void AppendTranslatedExit(SqlInsert node) => - translator.Translate(context, node, InsertSection.Exit); - protected void AppendTranslated(SqlJoinExpression node, JoinSection section) { AppendSpaceIfNecessary(); translator.Translate(context, node, section); } - protected void AppendTranslated(SqlLike node, LikeSection section) - { - AppendSpaceIfNecessary(); - translator.Translate(context, node, section); - AppendSpaceIfNecessary(); - } - - protected void AppendTranslatedEntry(SqlLike node) - { - AppendSpaceIfNecessary(); - translator.Translate(context, node, LikeSection.Entry); - } - - protected void AppendTranslatedExit(SqlLike node) => - translator.Translate(context, node, LikeSection.Exit); - protected void AppendTranslated(SqlMatch node, MatchSection section) { AppendSpaceIfNecessary(); @@ -2719,21 +2643,11 @@ protected void AppendTranslated(SqlRow node, NodeSection section) => protected void AppendTranslated(SqlRowNumber node, NodeSection section) => translator.Translate(context, node, section); - protected void AppendTranslated(SqlSelect node, SelectSection section) - { - AppendSpaceIfNecessary(); - translator.Translate(context, node, section); - AppendSpaceIfNecessary(); - } - - protected void AppendTranslatedEntry(SqlSelect node) - { - translator.Translate(context, node, SelectSection.Entry); - AppendSpaceIfNecessary(); - } + protected void AppendTranslatedEntry(SqlSelect node) => + translator.SelectEntry(context, node); protected void AppendTranslatedExit(SqlSelect node) => - translator.Translate(context, node, SelectSection.Exit); + translator.SelectExit(context, node); protected void AppendTranslated(SqlStatementBlock node, NodeSection section) { @@ -2762,19 +2676,6 @@ protected void AppendTranslated(SqlTrim node, TrimSection section) protected void AppendTranslated(SqlUnary node, NodeSection section) => translator.Translate(context, node, section); - protected void AppendTranslated(SqlUpdate node, UpdateSection section) - { - AppendSpaceIfNecessary(); - translator.Translate(context, node, section); - AppendSpaceIfNecessary(); - } - - protected void AppendTranslatedEntry(SqlUpdate node) => - translator.Translate(context, node, UpdateSection.Entry); - - protected void AppendTranslatedExit(SqlUpdate node) => - translator.Translate(context, node, UpdateSection.Exit); - protected void AppendTranslatedEntry(SqlUserColumn node) { AppendSpaceIfNecessary(); @@ -2790,13 +2691,6 @@ protected void AppendTranslated(SqlVariable node) translator.Translate(context, node); } - protected void AppendTranslated(SqlWhile node, WhileSection section) - { - AppendSpaceIfNecessary(); - translator.Translate(context, node, section); - AppendSpaceIfNecessary(); - } - protected void AppendTranslated(SqlExtract extract, ExtractSection section) { AppendSpaceIfNecessary(); diff --git a/Orm/Xtensive.Orm/Sql/Compiler/SqlNodeSections.cs b/Orm/Xtensive.Orm/Sql/Compiler/SqlNodeSections.cs index 51071ec2c2..31151f6f9e 100644 --- a/Orm/Xtensive.Orm/Sql/Compiler/SqlNodeSections.cs +++ b/Orm/Xtensive.Orm/Sql/Compiler/SqlNodeSections.cs @@ -44,14 +44,6 @@ public enum ConstraintSection ForeignKey = 5, ReferencedColumns = 6, } - - public enum BetweenSection - { - Entry = 0, - Exit = 1, - Between = 2, - And = 3, - } public enum CaseSection { @@ -63,13 +55,6 @@ public enum CaseSection Else = 5, } - public enum ColumnSection - { - Entry = 0, - Exit = 1, - AliasDeclaration = 2, - } - public enum CreateDomainSection { Entry = 0, @@ -123,13 +108,6 @@ public enum DeleteSection Limit = 4, } - public enum FetchSection - { - Entry = 0, - Exit = 1, - Targets = 2, - } - public enum FunctionCallSection { Entry = 0, @@ -151,40 +129,11 @@ public enum SequenceDescriptorSection AlterMinValue = 7, } - public enum IfSection - { - Entry = 0, - Exit = 1, - True = 2, - False = 3, - } - - public enum InsertSection - { - Entry = 0, - Exit = 1, - ColumnsEntry = 2, - ColumnsExit = 4, - ValuesEntry = 3, - ValuesExit = 5, - DefaultValues = 6, - From = 7, - } - public enum JoinSection { Entry = 0, Exit = 1, Specification = 2, - Condition = 3, - } - - public enum LikeSection - { - Entry = 0, - Exit = 1, - Like = 2, - Escape = 3, } public enum MatchSection @@ -194,23 +143,6 @@ public enum MatchSection Specification = 2, } - public enum SelectSection - { - Entry = 0, - Exit = 1, - From = 3, - Where = 4, - GroupBy = 5, - Having = 6, - OrderBy = 7, - HintsEntry = 8, - HintsExit = 9, - Limit = 10, - Offset = 11, - LimitEnd = 12, - OffsetEnd = 13, - } - public enum TableSection { Entry = 0, @@ -256,23 +188,6 @@ public enum ArraySection EmptyArray = 2, } - public enum UpdateSection - { - Entry = 0, - Exit = 1, - Set = 2, - From = 3, - Where = 4, - Limit = 5, - } - - public enum WhileSection - { - Entry = 0, - Exit = 1, - Statement = 2, - } - public enum QueryExpressionSection { Entry = 0, diff --git a/Orm/Xtensive.Orm/Sql/Compiler/SqlTranslator.cs b/Orm/Xtensive.Orm/Sql/Compiler/SqlTranslator.cs index 9eb356c69c..633a87f77a 100644 --- a/Orm/Xtensive.Orm/Sql/Compiler/SqlTranslator.cs +++ b/Orm/Xtensive.Orm/Sql/Compiler/SqlTranslator.cs @@ -385,24 +385,18 @@ public virtual void Translate(SqlCompilerContext context, SqlAssignment node, No } } - /// - /// Translates expression and writes result to to . - /// - /// The compiler context. - /// Expression to translate. - /// Particular section to translate. - public virtual void Translate(SqlCompilerContext context, SqlBetween node, BetweenSection section) + public virtual void BetweenBetween(SqlCompilerContext context, SqlBetween node) { - switch (section) { - case BetweenSection.Between: - Translate(context.Output, node.NodeType); - break; - case BetweenSection.And: - _ = context.Output.Append("AND"); - break; - } + context.Output.AppendSpaceIfNecessary(); + Translate(context.Output, node.NodeType); + context.Output.AppendSpaceIfNecessary(); } + public virtual void BetweenAnd(SqlCompilerContext context, SqlBetween node) => + context.Output.AppendSpaceIfNecessary() + .Append("AND") + .AppendSpaceIfNecessary(); + /// /// Translates expression and writes result to to . /// @@ -511,23 +505,19 @@ public virtual void Translate(SqlCompilerContext context, SqlCollate node, NodeS } } - /// - /// Translates node and writes result to to . - /// - /// The compiler context. - /// Node to translate. - /// Particular section to translate. - public virtual void Translate(SqlCompilerContext context, SqlColumnRef node, ColumnSection section) + public virtual void ColumnEntry(SqlCompilerContext context, SqlColumnRef node) { var output = context.Output; - switch (section) { - case ColumnSection.Entry: - TranslateIdentifier(output, node.Name); - break; - case ColumnSection.AliasDeclaration when !string.IsNullOrEmpty(node.Name): - _ = output.Append(" AS "); - TranslateIdentifier(output, node.Name); - break; + output.AppendSpaceIfNecessary(); + TranslateIdentifier(output, node.Name); + output.AppendSpaceIfNecessary(); + } + + public virtual void ColumnAliasDeclaration(SqlCompilerContext context, SqlColumnRef node) + { + if (!string.IsNullOrEmpty(node.Name)) { + _ = context.Output.Append(" AS "); + TranslateIdentifier(context.Output, node.Name); } } @@ -1266,26 +1256,14 @@ public virtual void Translate(SqlCompilerContext context, SqlDropView node) _ = context.Output.Append(node.Cascade ? " CASCADE" : " RESTRICT"); } - /// - /// Translates statement and writes result to to . - /// - /// The compiler context. - /// Statement to translate. - /// Particular section to translate. - public virtual void Translate(SqlCompilerContext context, SqlFetch node, FetchSection section) + public virtual void FetchEntry(SqlCompilerContext context, SqlFetch node) => + context.Output.Append("FETCH ").Append(node.Option.ToString()); + + public virtual void FetchTarget(SqlCompilerContext context, SqlFetch node) { - switch (section) { - case FetchSection.Entry: - _ = context.Output.Append("FETCH ") - .Append(node.Option.ToString()); - break; - case FetchSection.Targets: - _ = context.Output.Append("FROM ") - .Append(node.Cursor.Name); - if (node.Targets.Count != 0) { - _ = context.Output.Append(" INTO"); - } - break; + _ = context.Output.AppendSpaceIfNecessary().Append("FROM ").Append(node.Cursor.Name); + if (node.Targets.Count != 0) { + _ = context.Output.Append(" INTO"); } } @@ -1380,60 +1358,53 @@ public virtual void Translate(SqlCompilerContext context, SqlExtract extract, Ex }); } - /// - /// Translates expression and writes result to to . - /// - /// The compiler context. - /// Expression to translate. - /// Particular section to translate. - public virtual void Translate(SqlCompilerContext context, SqlIf node, IfSection section) + public virtual void IfEntry(SqlCompilerContext context) => + context.Output.AppendSpaceIfNecessary().Append("IF"); + + public virtual void IfTrue(SqlCompilerContext context) => + context.Output.AppendSpaceIfNecessary().Append("BEGIN"); + + public virtual void IfFalse(SqlCompilerContext context) => + context.Output.AppendSpaceIfNecessary().Append("END BEGIN"); + + public virtual void IfExit(SqlCompilerContext context) => + context.Output.AppendSpaceIfNecessary().Append("END"); + + public virtual void InsertEntry(SqlCompilerContext context) => + context.Output.Append("INSERT INTO"); + + public virtual void InsertColumnsEntry(SqlCompilerContext context, SqlInsert node) { - _ = context.Output.Append(section switch { - IfSection.Entry => "IF", - IfSection.True => "BEGIN", - IfSection.False => "END BEGIN", - IfSection.Exit => "END", - _ => string.Empty - }); + context.Output.AppendSpaceIfNecessary(); + if (node.ValueRows.Count > 0) { + context.Output.Append("("); + } } - /// - /// Translates statement and writes result to to . - /// - /// The compiler context. - /// Statement to translate. - /// Particular section to translate. - public virtual void Translate(SqlCompilerContext context, SqlInsert node, InsertSection section) + public virtual void InsertColumnsExit(SqlCompilerContext context, SqlInsert node) { - var output = context.Output; - switch (section) { - case InsertSection.Entry: - _ = output.Append("INSERT INTO"); - break; - case InsertSection.ColumnsEntry when node.ValueRows.Count > 0: - _ = output.AppendOpeningPunctuation("("); - break; - case InsertSection.ColumnsExit when node.ValueRows.Count > 0: - _ = output.Append(")"); - break; - case InsertSection.From: - _ = output.Append("FROM"); - break; - case InsertSection.ValuesEntry when node.ValueRows.Count == 0: - _ = output.AppendOpeningPunctuation("VALUES ("); - break; - case InsertSection.ValuesEntry when node.ValueRows.Count > 0: - _ = output.AppendOpeningPunctuation("VALUES "); - break; - case InsertSection.ValuesExit when node.ValueRows.Count == 0: - _ = output.Append(")"); - break; - case InsertSection.DefaultValues: - _ = output.Append("DEFAULT VALUES"); - break; + context.Output.AppendSpaceIfNecessary(); + if (node.ValueRows.Count > 0) { + context.Output.Append(")"); + } + } + + public virtual void InsertValuesEntry(SqlCompilerContext context, SqlInsert node) => + context.Output.AppendSpaceIfNecessary().AppendOpeningPunctuation(node.ValueRows.Count == 0 ? "VALUES (" : "VALUES "); + + public virtual void InsertValuesExit(SqlCompilerContext context, SqlInsert node) + { + context.Output.AppendSpaceIfNecessary(); + if (node.ValueRows.Count == 0) { + context.Output.Append(")"); } } + public virtual void InsertDefaultValues(SqlCompilerContext context) => + context.Output.AppendSpaceIfNecessary().AppendOpeningPunctuation("DEFAULT VALUES"); + + public virtual void InsertExit(SqlCompilerContext context) { } + /// /// Translates node and writes result to to . /// @@ -1461,39 +1432,30 @@ public virtual void Translate(SqlCompilerContext context, SqlJoinExpression node Translate(output, node.JoinType); _ = output.Append(" JOIN"); break; - case JoinSection.Condition: - _ = output.Append(node.JoinType == SqlJoinType.UsingJoin ? "USING" : "ON"); - break; case JoinSection.Exit when explicitJoinOrder: _ = output.Append(")"); break; } } - /// - /// Translates statement and writes result to to . - /// - /// The compiler context. - /// Statement to translate. - /// Particular section to translate. - public virtual void Translate(SqlCompilerContext context, SqlLike node, LikeSection section) - { - var output = context.Output; - switch (section) { - case LikeSection.Entry: - _ = output.Append("("); - break; - case LikeSection.Exit: - _ = output.AppendClosingPunctuation(")"); - break; - case LikeSection.Like: - _ = output.Append(node.Not ? "NOT LIKE" : "LIKE"); - break; - case LikeSection.Escape: - _ = output.Append("ESCAPE"); - break; - } - } + public virtual void JoinCondition(SqlCompilerContext context, SqlJoinExpression node) => + context.Output.AppendSpacePrefixed(node.JoinType == SqlJoinType.UsingJoin ? "USING " : "ON "); + + public virtual void LikeEntry(SqlCompilerContext context) => + context.Output.AppendSpaceIfNecessary().Append("("); + + public virtual void LikeExit(SqlCompilerContext context) => + context.Output.AppendClosingPunctuation(")"); + + public virtual void LikeLike(SqlCompilerContext context, SqlLike node) => + context.Output.AppendSpaceIfNecessary() + .Append(node.Not ? "NOT LIKE" : "LIKE") + .AppendSpaceIfNecessary(); + + public virtual void LikeEscape(SqlCompilerContext context) => + context.Output.AppendSpaceIfNecessary() + .Append("ESCAPE") + .AppendSpaceIfNecessary(); /// /// Translates literal values like numbers, string, char, TimeSpan, DateTime values, etc. @@ -1608,20 +1570,8 @@ public virtual void Translate(SqlCompilerContext context, SqlNull node) => public virtual void Translate(SqlCompilerContext context, SqlOpenCursor node) => context.Output.Append("OPEN ").Append(node.Cursor.Name); - /// - /// Translates node and writes result to to . - /// - /// The compiler context. - /// Node to translate. - /// Particular section to translate. - public virtual void Translate(SqlCompilerContext context, SqlOrder node, NodeSection section) - { - switch (section) { - case NodeSection.Exit: - TranslateSortOrder(context.Output, node.Ascending); - break; - } - } + public virtual void OrderExit(SqlCompilerContext context, SqlOrder node) => + TranslateSortOrder(context.Output, node.Ascending); /// /// Translates statement and writes result to to . @@ -1705,26 +1655,35 @@ public virtual void Translate(SqlCompilerContext context, SqlRenameTable node) TranslateIdentifier(context.Output, node.NewName); } - /// - /// Translates statement and writes result to to . - /// - /// The compiler context. - /// Statement to translate. - /// Particular section to translate. - public virtual void Translate(SqlCompilerContext context, SqlSelect node, SelectSection section) - { - _ = context.Output.Append(section switch { - SelectSection.Entry => node.Distinct ? "SELECT DISTINCT" : "SELECT", - SelectSection.From => "FROM", - SelectSection.Where => "WHERE", - SelectSection.GroupBy => "GROUP BY", - SelectSection.Having => "HAVING", - SelectSection.OrderBy => "ORDER BY", - SelectSection.Limit => "LIMIT", - SelectSection.Offset => "OFFSET", - _ => string.Empty - }); - } + public virtual void SelectEntry(SqlCompilerContext context, SqlSelect node) => + context.Output.Append(node.Distinct ? "SELECT DISTINCT " : "SELECT "); + + public virtual void SelectFrom(SqlCompilerContext context, SqlSelect node) => + context.Output.AppendSpacePrefixed("FROM "); + + public virtual void SelectWhere(SqlCompilerContext context, SqlSelect node) => + context.Output.AppendSpacePrefixed("WHERE "); + + public virtual void SelectLimit(SqlCompilerContext context, SqlSelect node) => + context.Output.AppendSpacePrefixed("LIMIT "); + + public virtual void SelectGroupBy(SqlCompilerContext context, SqlSelect node) => + context.Output.AppendSpacePrefixed("GROUP BY "); + + public virtual void SelectOrderBy(SqlCompilerContext context, SqlSelect node) => + context.Output.AppendSpacePrefixed("ORDER BY "); + + public virtual void SelectHaving(SqlCompilerContext context, SqlSelect node) => + context.Output.AppendSpacePrefixed("HAVING "); + + public virtual void SelectOffset(SqlCompilerContext context, SqlSelect node) => + context.Output.AppendSpacePrefixed("OFFSET "); + + public virtual void SelectLimitEnd(SqlCompilerContext context, SqlSelect node) { } + public virtual void SelectOffsetEnd(SqlCompilerContext context, SqlSelect node) { } + public virtual void SelectExit(SqlCompilerContext context, SqlSelect node) { } + public virtual void SelectHintsEntry(SqlCompilerContext context, SqlSelect node) { } + public virtual void SelectHintsExit(SqlCompilerContext context, SqlSelect node) { } /// /// Translates statement and writes result to to . @@ -1861,23 +1820,20 @@ public virtual void Translate(SqlCompilerContext context, SqlUnary node, NodeSec } } - /// - /// Translates statement and writes result to to . - /// - /// The compiler context. - /// Statement to translate. - /// Particular section to translate. - public virtual void Translate(SqlCompilerContext context, SqlUpdate node, UpdateSection section) - { - _ = context.Output.Append(section switch { - UpdateSection.Entry => "UPDATE", - UpdateSection.Set => "SET", - UpdateSection.From => "FROM", - UpdateSection.Where => (node.Where is SqlCursor) ? "WHERE CURRENT OF" : "WHERE", - UpdateSection.Limit => "LIMIT", - _ => string.Empty - }); - } + public virtual void UpdateSet(SqlCompilerContext context) => + context.Output.AppendSpaceIfNecessary().Append("SET").AppendSpaceIfNecessary(); + + public virtual void UpdateFrom(SqlCompilerContext context) => + context.Output.AppendSpaceIfNecessary().Append("FROM").AppendSpaceIfNecessary(); + + public virtual void UpdateWhere(SqlCompilerContext context, SqlUpdate node) => + context.Output.AppendSpaceIfNecessary().Append((node.Where is SqlCursor) ? "WHERE CURRENT OF" : "WHERE").AppendSpaceIfNecessary(); + + public virtual void UpdateLimit(SqlCompilerContext context) => + context.Output.AppendSpaceIfNecessary().Append("LIMIT").AppendSpaceIfNecessary(); + + public virtual void UpdateEntry(SqlCompilerContext context, SqlUpdate node) => + context.Output.Append("UPDATE "); /// /// Translates node and writes result to to . @@ -1918,26 +1874,20 @@ public virtual void Translate(SqlCompilerContext context, SqlUserFunctionCall no /// Expression to translate. public virtual void Translate(SqlCompilerContext context, SqlVariable node) => context.Output.Append("@").Append(node.Name); - /// - /// Translates statement and writes result to to . - /// - /// The compiler context. - /// Statement to translate. - /// Particular section to translate. - public virtual void Translate(SqlCompilerContext context, SqlWhile node, WhileSection section) - { - switch (section) { - case WhileSection.Entry: - _ = context.Output.AppendOpeningPunctuation("WHILE ("); - break; - case WhileSection.Statement: - _ = context.Output.AppendClosingPunctuation(") BEGIN"); - break; - case WhileSection.Exit: - _ = context.Output.Append("END"); - break; - } - } + public virtual void WhileEntry(SqlCompilerContext context) => + context.Output.AppendSpaceIfNecessary() + .AppendOpeningPunctuation("WHILE (") + .AppendSpaceIfNecessary(); + + public virtual void WhileStatement(SqlCompilerContext context) => + context.Output.AppendSpaceIfNecessary() + .AppendClosingPunctuation(") BEGIN") + .AppendSpaceIfNecessary(); + + public virtual void WhileExit(SqlCompilerContext context) => + context.Output.AppendSpaceIfNecessary() + .AppendClosingPunctuation("END") + .AppendSpaceIfNecessary(); /// /// Translates statement and writes result to to .