Skip to content

Commit

Permalink
Added support (and unit tests) for Batch Commands. Can parse SQL that…
Browse files Browse the repository at this point in the history
… contains many different sql commands with terminators in the same batch as opposed to just a single command. jehugaleahsa#14
  • Loading branch information
dazinator committed Oct 5, 2015
1 parent b316d0e commit 4d65afa
Show file tree
Hide file tree
Showing 15 changed files with 322 additions and 24 deletions.
27 changes: 23 additions & 4 deletions SQLGeneration.Tests/CommandBuilderTester.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1038,17 +1038,36 @@ public void TestDelete_WhereClause()
#region Batch

/// <summary>
/// This sees whether we can reproduce multiple insert statements in a batch.
/// This sees whether we can reproduce a batch of SQL statements.
/// </summary>
[TestMethod]
public void TestBatch_MixtureOfStatementsWithSemiColons()
{
string commandText = @"INSERT INTO Table (TestCol) VALUES(';');SELECT 1 UNION ALL SELECT 1;SELECT CASE WHEN Table.Column = 'Adm;in' THEN 'Administ;rator' ELSE 'Us;er' END FROM Table";
assertCanReproduce(commandText);
}

/// <summary>
/// This sees whether we can reproduce multiple insert statements in a batch using a terminator.
/// </summary>
[TestMethod]
public void TestBatch_MultipleInserts()
{
string commandText = @"INSERT INTO Table VALUES();
INSERT INTO Table VALUES()";
string commandText = @"INSERT INTO Table VALUES();INSERT INTO Table VALUES()";
assertCanReproduce(commandText);
}

#endregion
/// <summary>
/// This tests whether the terminator is persisted when we parse and reproduce the sql.
/// </summary>
[TestMethod]
public void TestBatch_TerminatorPersists()
{
string commandText = @"INSERT INTO Table VALUES();";
assertCanReproduce(commandText);
}

#endregion

private void assertCanReproduce(string commandText, CommandBuilderOptions options = null)
{
Expand Down
113 changes: 113 additions & 0 deletions SQLGeneration/Builders/BatchBuilder.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace SQLGeneration.Builders
{

/// <summary>
/// Builds a string that contains many individual commands seprated by terminators.
/// </summary>
public class BatchBuilder : ICommand
{
private readonly IList<ICommand> _commands;
private bool _hasTerminator = false;

/// <summary>
/// Initializes a new instance of a BatchBuilder.
/// </summary>
/// <param name="commands">The commands to be in the batch.</param>
public BatchBuilder(IList<ICommand> commands)
{
_commands = commands;
}

/// <summary>
/// Initializes a new instance of a BatchBuilder.
/// </summary>
public BatchBuilder()
{
_commands = new List<ICommand>();
}

/// <summary>
/// Adds the command to the batch.
/// </summary>
/// <param name="command">The command to add.</param>
public void AddCommand(ICommand command)
{
if (command == null)
{
throw new ArgumentNullException("command");
}
_commands.Add(command);
}

/// <summary>
/// Removes the command from the batch.
/// </summary>
/// <param name="command">The command to remove.</param>
/// <returns>True if the command was removed; otherwise, false.</returns>
public bool RemoveCommand(ICommand command)
{
if (command == null)
{
throw new ArgumentNullException("command");
}
return _commands.Remove(command);
}

/// <summary>
/// Gets the command at the specified index.
/// </summary>
/// <param name="index"></param>
/// <returns></returns>
public ICommand GetCommand(int index)
{
return _commands[index];
}

/// <summary>
/// Returns the commands as an IEnumerable.
/// </summary>
/// <returns></returns>
public IEnumerable<ICommand> Commands()
{
return _commands.AsEnumerable();
}

/// <summary>
/// Returns whether there is a single command in the batch.
/// </summary>
/// <returns></returns>
public bool IsSingleCommand()
{
return !(_commands.Count > 1);
}

/// <summary>
/// Gets whether this command has a terminator.
/// </summary>
public bool HasTerminator
{
get
{
return _hasTerminator;
}
set
{
_hasTerminator = value;
}
}

/// <summary>
/// Accepts a visitor.
/// </summary>
/// <param name="visitor"></param>
public void Accept(BuilderVisitor visitor)
{
visitor.VisitBatch(this);
}
}
}
8 changes: 8 additions & 0 deletions SQLGeneration/Builders/BuilderVisitor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,14 @@ protected internal virtual void VisitAliasedSource(AliasedSource aliasedSource)

}

/// <summary>
/// Visits a Batch builder.
/// </summary>
/// <param name="item">The item to visit.</param>
protected internal virtual void VisitBatch(BatchBuilder item)
{
}

/// <summary>
/// Visits a BetweenFilter builder.
/// </summary>
Expand Down
6 changes: 6 additions & 0 deletions SQLGeneration/Builders/CommandOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ public CommandOptions()
VerboseDeleteStatement = true;
VerboseInnerJoin = true;
VerboseOuterJoin = true;
Terminator = ';';
}

/// <summary>
Expand Down Expand Up @@ -82,5 +83,10 @@ public CommandOptions Clone()
/// Gets or sets whether columns should be fully qualified within a DELETE statement.
/// </summary>
public bool QualifyDeleteColumns { get; set; }

/// <summary>
/// Gets or sets the terminator to be used.
/// </summary>
public char Terminator { get; set; }
}
}
16 changes: 16 additions & 0 deletions SQLGeneration/Builders/DeleteBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ public class DeleteBuilder : IFilteredCommand
{
private readonly AliasedSource _table;
private readonly FilterGroup _where;
private bool _hasTerminator = false;

/// <summary>
/// Initializes a new instance of a DeleteBuilder.
Expand Down Expand Up @@ -70,6 +71,21 @@ public bool RemoveWhere(IFilter filter)
return _where.RemoveFilter(filter);
}

/// <summary>
/// Gets whether this command has a terminator.
/// </summary>
public bool HasTerminator
{
get
{
return _hasTerminator;
}
set
{
_hasTerminator = value;
}
}

void IVisitableBuilder.Accept(BuilderVisitor visitor)
{
visitor.VisitDelete(this);
Expand Down
4 changes: 4 additions & 0 deletions SQLGeneration/Builders/ICommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,9 @@ namespace SQLGeneration.Builders
/// </summary>
public interface ICommand : IVisitableBuilder
{
/// <summary>
/// Gets whether the command has a terminator.
/// </summary>
bool HasTerminator { get; set; }
}
}
18 changes: 18 additions & 0 deletions SQLGeneration/Builders/InsertBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ public class InsertBuilder : ICommand
private readonly AliasedSource _table;
private readonly List<Column> _columns;
private readonly IValueProvider _values;
private bool _hasTerminator = false;

/// <summary>
/// Initializes a new instance of a InsertBuilder.
Expand Down Expand Up @@ -85,9 +86,26 @@ public IValueProvider Values
get { return _values; }
}

/// <summary>
/// Gets whether this command has a terminator.
/// </summary>
public bool HasTerminator
{
get
{
return _hasTerminator;
}
set
{
_hasTerminator = value;
}
}

void IVisitableBuilder.Accept(BuilderVisitor visitor)
{
visitor.VisitInsert(this);
}


}
}
16 changes: 16 additions & 0 deletions SQLGeneration/Builders/SelectBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ public class SelectBuilder : ISelectBuilder, IFilteredCommand
private readonly List<IGroupByItem> _groupBy;
private readonly FilterGroup _having;
private readonly SourceCollection sources;
private bool _hasTerminator = false;

/// <summary>
/// Initializes a new instance of a SelectBuilder.
Expand Down Expand Up @@ -371,6 +372,21 @@ bool IValueProvider.IsValueList
get { return false; }
}

/// <summary>
/// Gets whether this command has a terminator.
/// </summary>
public bool HasTerminator
{
get
{
return _hasTerminator;
}
set
{
_hasTerminator = value;
}
}

void IVisitableBuilder.Accept(BuilderVisitor visitor)
{
visitor.VisitSelect(this);
Expand Down
16 changes: 16 additions & 0 deletions SQLGeneration/Builders/SelectCombiner.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ public abstract class SelectCombiner : ISelectBuilder
private readonly ISelectBuilder leftHand;
private readonly ISelectBuilder rightHand;
private readonly List<OrderBy> orderBy;
private bool _hasTerminator = false;

/// <summary>
/// Initializes a new instance of a SelectCombiner.
Expand Down Expand Up @@ -116,6 +117,21 @@ bool IValueProvider.IsValueList
get { return false; }
}

/// <summary>
/// Gets whether this command has a terminator.
/// </summary>
public bool HasTerminator
{
get
{
return _hasTerminator;
}
set
{
_hasTerminator = value;
}
}

void IVisitableBuilder.Accept(BuilderVisitor visitor)
{
OnAccept(visitor);
Expand Down
16 changes: 16 additions & 0 deletions SQLGeneration/Builders/UpdateBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ public class UpdateBuilder : IFilteredCommand
private readonly AliasedSource _table;
private readonly IList<Setter> _setters;
private readonly FilterGroup _where;
private bool _hasTerminator = false;

/// <summary>
/// Initializes a new instance of a UpdateBuilder.
Expand Down Expand Up @@ -108,6 +109,21 @@ public bool RemoveWhere(IFilter filter)
return _where.RemoveFilter(filter);
}

/// <summary>
/// Gets whether this command has a terminator.
/// </summary>
public bool HasTerminator
{
get
{
return _hasTerminator;
}
set
{
_hasTerminator = value;
}
}

void IVisitableBuilder.Accept(BuilderVisitor visitor)
{
visitor.VisitUpdate(this);
Expand Down
Loading

0 comments on commit 4d65afa

Please sign in to comment.