diff --git a/SQLGeneration.Tests/CommandBuilderTester.cs b/SQLGeneration.Tests/CommandBuilderTester.cs index 767635d..d2834d4 100644 --- a/SQLGeneration.Tests/CommandBuilderTester.cs +++ b/SQLGeneration.Tests/CommandBuilderTester.cs @@ -825,7 +825,7 @@ public void TestSelect_FunctionWithBetweenFraming() /// [TestMethod] public void TestSelect_FunctionWithStartFraming() - { + { string commandText = "SELECT sale.prod_id, sale.month_num, sale.sales, SUM(sale.sales) OVER (PARTITION BY sale.prod_id ORDER BY sale.month_num ROWS 12 PRECEDING) FROM sale"; assertCanReproduce(commandText); } @@ -1025,6 +1025,21 @@ public void TestDelete_WhereClause() #endregion + #region Batch + + /// + /// This sees whether we can reproduce multiple insert statements in a batch. + /// + [TestMethod] + public void TestBatch_MultipleInserts() + { + string commandText = @"INSERT INTO Table VALUES(); + INSERT INTO Table VALUES()"; + assertCanReproduce(commandText); + } + + #endregion + private void assertCanReproduce(string commandText, CommandBuilderOptions options = null) { CommandBuilder builder = new CommandBuilder(); @@ -1049,7 +1064,7 @@ public void TestSelect_AddFilter() customerId.Qualify = false; Placeholder parameter = new Placeholder("@customerId"); select.AddWhere(new EqualToFilter(customerId, parameter)); - + Formatter formatter = new Formatter(); string actual = formatter.GetCommandText(select); string expected = "SELECT * FROM Customer WHERE CustomerId = @customerId"; @@ -1078,7 +1093,7 @@ public void TestSelect_ExtraWhitespace() [TestMethod] public void TestSelect_Newlines() { - string commandText = + string commandText = @"SELECT * FROM Table1 @@ -1213,7 +1228,7 @@ public void TestFilterGroup_Optimize_SimplifiesConditions() new EqualToFilter(new Column("FirstName"), new StringLiteral("Max")), new FilterGroup(Conjunction.And, new EqualToFilter(new Column("LastName"), new StringLiteral("Planck"))))); - + wrapInParentheses(topFilter, true); SelectBuilder selectBuilder = new SelectBuilder(); diff --git a/SQLGeneration/Parsing/SqlGrammar.cs b/SQLGeneration/Parsing/SqlGrammar.cs index 4c386d3..0c359f2 100644 --- a/SQLGeneration/Parsing/SqlGrammar.cs +++ b/SQLGeneration/Parsing/SqlGrammar.cs @@ -71,9 +71,9 @@ public SqlGrammar(SqlTokenRegistry registry = null) /// /// Gets the default instance of the SqlGrammar. /// - public static SqlGrammar Default - { - get { return instance; } + public static SqlGrammar Default + { + get { return instance; } } #region Start @@ -89,8 +89,8 @@ public static class Start public const string Name = "Start"; /// - /// Gets the name for the SELECT statement option. - /// + /// Gets the name for the SELECT statement option. + /// public const string SelectStatement = "select_statement"; /// @@ -107,6 +107,13 @@ public static class Start /// Gets the name for the DELETE statement option. /// public const string DeleteStatement = "delete_statement"; + + /// + /// Gets the name for the Terminator of a statement. + /// + public const string Terminator = "terminator"; + + } private void defineStart() @@ -116,7 +123,8 @@ private void defineStart() .Add(Start.SelectStatement, Expression(SelectStatement.Name)) .Add(Start.InsertStatement, Expression(InsertStatement.Name)) .Add(Start.UpdateStatement, Expression(UpdateStatement.Name)) - .Add(Start.DeleteStatement, Expression(DeleteStatement.Name))); + .Add(Start.DeleteStatement, Expression(DeleteStatement.Name))) + .Add(Start.Terminator, false, Token(SqlTokenRegistry.LineTerminator)); } #endregion @@ -184,8 +192,8 @@ public static class SelectExpression public const string Name = "SelectExpression"; /// - /// Describes the structure of the leading SELECT expression when it is surrounded by parenthesis. - /// + /// Describes the structure of the leading SELECT expression when it is surrounded by parenthesis. + /// public static class Wrapped { /// @@ -884,7 +892,7 @@ public static class Multiple /// Gets the identifier for the comma separator. /// public const string Comma = "comma"; - + /// /// Gets the identifier for the rest of the projection list. /// @@ -1899,7 +1907,7 @@ public static class Like /// Gets the identifier indicating whether the filter is doing a string comparison. /// public const string Name = "Like"; - + /// /// Gets the identifier for the expression being compared. /// @@ -2665,7 +2673,7 @@ public static class Wrapped /// public const string RightParenthesis = "right_parenthesis"; } - + /// /// Gets the identifier for an unwrapped item. /// @@ -3686,7 +3694,7 @@ public static class Multiple /// Gets the identifier for the dot separator. /// public const string Dot = "dot"; - + /// /// Gets the identifier for the rest of the identifiers. /// diff --git a/SQLGeneration/Parsing/SqlTokenRegistry.cs b/SQLGeneration/Parsing/SqlTokenRegistry.cs index c5da1b5..4b2ecca 100644 --- a/SQLGeneration/Parsing/SqlTokenRegistry.cs +++ b/SQLGeneration/Parsing/SqlTokenRegistry.cs @@ -377,6 +377,11 @@ public class SqlTokenRegistry : TokenRegistry /// public const string End = "End"; + /// + /// Gets the identifier for the Line Terminator which can be used to seperate SQL statements in a batch. + /// + public const string LineTerminator = "LineTerminator"; + /// /// Initializes a new instance of a SqlTokenizer. /// @@ -458,6 +463,7 @@ public SqlTokenRegistry() Define(Number, @"[-+]?\d*\.?\d+([eE][-+]?\d+)?"); Define(RightParenthesis, @"\)"); Define(String, @"'([^']|'')*'"); + Define(LineTerminator, @"('(?:\\.|''|[^'])*(')?)|(;)"); } } }