Skip to content

Commit

Permalink
Merge pull request #89 from abe545/add-quote-options
Browse files Browse the repository at this point in the history
Add quote options.
  • Loading branch information
abe545 authored Oct 14, 2016
2 parents c60ad79 + f692ab6 commit 8b59b41
Show file tree
Hide file tree
Showing 7 changed files with 186 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,9 @@
<Compile Include="..\CodeOnlyStoredProcedure\NamespaceDoc.cs">
<Link>NamespaceDoc.cs</Link>
</Compile>
<Compile Include="..\CodeOnlyStoredProcedure\ObjectQuoteStyle.cs">
<Link>ObjectQuoteStyle.cs</Link>
</Compile>
<Compile Include="..\CodeOnlyStoredProcedure\OptionalResultAttribute.cs">
<Link>OptionalResultAttribute.cs</Link>
</Compile>
Expand Down Expand Up @@ -351,7 +354,7 @@
<ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
<Import Condition="'$(CodeContractsImported)' != 'true' AND '$(DontImportCodeContracts)' != 'true'" Project="$(CodeContractsInstallDir)\MsBuild\v$(VisualStudioVersion)\Microsoft.CodeContracts.targets"/>
<Import Condition="'$(CodeContractsImported)' != 'true' AND '$(DontImportCodeContracts)' != 'true'" Project="$(CodeContractsInstallDir)\MsBuild\v$(VisualStudioVersion)\Microsoft.CodeContracts.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
Expand Down
3 changes: 2 additions & 1 deletion CodeOnlyStoredProcedure/CodeOnlyStoredProcedure.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@
<Compile Include="HierarchicalStoredProcedure.cs" />
<Compile Include="IDataTransformer.cs" />
<Compile Include="IDbConnectionExtensions.cs" />
<Compile Include="ObjectQuoteStyle.cs" />
<Compile Include="OptionalResultAttribute.cs" />
<Compile Include="PropertyInfoExtensions.cs" />
<Compile Include="RowFactory\AccessorFactoryBase.cs" />
Expand Down Expand Up @@ -228,7 +229,7 @@
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
<Import Condition="'$(CodeContractsImported)' != 'true' AND '$(DontImportCodeContracts)' != 'true'" Project="$(CodeContractsInstallDir)\MsBuild\v$(VisualStudioVersion)\Microsoft.CodeContracts.targets"/>
<Import Condition="'$(CodeContractsImported)' != 'true' AND '$(DontImportCodeContracts)' != 'true'" Project="$(CodeContractsInstallDir)\MsBuild\v$(VisualStudioVersion)\Microsoft.CodeContracts.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
Expand Down
30 changes: 30 additions & 0 deletions CodeOnlyStoredProcedure/GlobalSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ internal class GlobalSettings
public bool ConvertAllNumericValues { get; set; }
public bool CloneConnectionForEachCall { get; set; } = true;

internal string OpenObjectQuote { get; private set; } = "[";
internal string CloseObjectQuote { get; private set; } = "]";

private GlobalSettings(bool isTestInstance = false)
{
IsTestInstance = isTestInstance;
Expand All @@ -27,6 +30,33 @@ public static IDisposable UseTestInstance()
return disposer;
}

public void SetObjectQuoteStyle(ObjectQuoteStyle style)
{
switch (style)
{
case ObjectQuoteStyle.DoubleQuote:
SetObjectQuoteStyle("\"", "\"");
break;

case ObjectQuoteStyle.BackTick:
SetObjectQuoteStyle("`", "`");
break;

case ObjectQuoteStyle.Brackets:
SetObjectQuoteStyle("[", "]");
break;

default:
throw new ArgumentException($"{style} is not a valid value for a ObjectQuoteStyle", "style");
}
}

public void SetObjectQuoteStyle(string openQuote, string closeQuote)
{
OpenObjectQuote = openQuote;
CloseObjectQuote = closeQuote;
}

private class Disposer : IDisposable
{
private readonly GlobalSettings toRestore;
Expand Down
5 changes: 4 additions & 1 deletion CodeOnlyStoredProcedure/IDbConnectionExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -357,8 +357,11 @@ internal static IDbCommand CreateCommand(
else
closeAfterExecute = null;

var open = GlobalSettings.Instance.OpenObjectQuote;
var close = GlobalSettings.Instance.CloseObjectQuote;

var cmd = connection.CreateCommand();
cmd.CommandText = $"[{schema}].[{name}]";
cmd.CommandText = $"{open}{schema}{close}.{open}{name}{close}";
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandTimeout = timeout;

Expand Down
21 changes: 21 additions & 0 deletions CodeOnlyStoredProcedure/ObjectQuoteStyle.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
namespace CodeOnlyStoredProcedure
{
/// <summary>
/// Describes the method of quoting objects in the database
/// </summary>
public enum ObjectQuoteStyle
{
/// <summary>
/// Uses " to open and close the quotes
/// </summary>
DoubleQuote,
/// <summary>
/// Uses ` to open and close the quotes
/// </summary>
BackTick,
/// <summary>
/// Uses [ open a quote, and ] to close it
/// </summary>
Brackets
}
}
1 change: 1 addition & 0 deletions CodeOnlyStoredProcedures.nuspec
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ Fixed bug where hierarchical result sets could not be marked as optional.
Hierarchies are now much faster to build, especially with large data sets.
DateTimeOffset is now fully supported (in the past you had to use attributes or the Fluent syntax to specify the DbType).
Hierarchical result sets will now match using case-insensitive names if the case-sensitive ones aren't found.
Added ability to specify the quote method for the objects, which allows you to call stored procedures in non-Microsoft products.

2.2.6
Fixed bug where dynamic stored procedures wouldn't dispose of the IDbCommand objects they created.
Expand Down
124 changes: 124 additions & 0 deletions CodeOnlyTests/IDbConnectionExtensionsTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,130 @@ public void Does_Not_Clone_When_Global_Option_Is_Set_To_Not_Clone_And_Opens_It_W
db.Verify(d => d.Open(), Times.Never());
}
}

[TestMethod]
public void Quotes_With_SquareBrackets_When_Set_Via_Enum()
{
using (GlobalSettings.UseTestInstance())
{
GlobalSettings.Instance.SetObjectQuoteStyle(ObjectQuoteStyle.Brackets);
var db = new Mock<IDbConnection>();
var db2 = new Mock<IDbConnection>();

db.As<ICloneable>().Setup(c => c.Clone()).Returns(db2.Object);

var cmd = new Mock<IDbCommand>();
cmd.SetupAllProperties();

db2.Setup(d => d.CreateCommand()).Returns(cmd.Object);

IDbConnection outConn;
var res = db.Object.CreateCommand("foo", "bar", 20, out outConn);

outConn.Should().NotBeNull();
res.Should().NotBeNull();
res.CommandText.Should().Be("[foo].[bar]");
res.CommandTimeout.Should().Be(20);
res.CommandType.Should().Be(CommandType.StoredProcedure);

db.As<ICloneable>().Verify(c => c.Clone(), Times.Once());
db2.Verify(d => d.CreateCommand(), Times.Once());
db2.Verify(d => d.Open(), Times.Once());
}
}

[TestMethod]
public void Quotes_With_DoubleQuotes_When_Set_Via_Enum()
{
using (GlobalSettings.UseTestInstance())
{
GlobalSettings.Instance.SetObjectQuoteStyle(ObjectQuoteStyle.DoubleQuote);
var db = new Mock<IDbConnection>();
var db2 = new Mock<IDbConnection>();

db.As<ICloneable>().Setup(c => c.Clone()).Returns(db2.Object);

var cmd = new Mock<IDbCommand>();
cmd.SetupAllProperties();

db2.Setup(d => d.CreateCommand()).Returns(cmd.Object);

IDbConnection outConn;
var res = db.Object.CreateCommand("foo", "bar", 20, out outConn);

outConn.Should().NotBeNull();
res.Should().NotBeNull();
res.CommandText.Should().Be("\"foo\".\"bar\"");
res.CommandTimeout.Should().Be(20);
res.CommandType.Should().Be(CommandType.StoredProcedure);

db.As<ICloneable>().Verify(c => c.Clone(), Times.Once());
db2.Verify(d => d.CreateCommand(), Times.Once());
db2.Verify(d => d.Open(), Times.Once());
}
}

[TestMethod]
public void Quotes_With_Backticks_When_Set_Via_Enum()
{
using (GlobalSettings.UseTestInstance())
{
GlobalSettings.Instance.SetObjectQuoteStyle(ObjectQuoteStyle.BackTick);
var db = new Mock<IDbConnection>();
var db2 = new Mock<IDbConnection>();

db.As<ICloneable>().Setup(c => c.Clone()).Returns(db2.Object);

var cmd = new Mock<IDbCommand>();
cmd.SetupAllProperties();

db2.Setup(d => d.CreateCommand()).Returns(cmd.Object);

IDbConnection outConn;
var res = db.Object.CreateCommand("foo", "bar", 20, out outConn);

outConn.Should().NotBeNull();
res.Should().NotBeNull();
res.CommandText.Should().Be("`foo`.`bar`");
res.CommandTimeout.Should().Be(20);
res.CommandType.Should().Be(CommandType.StoredProcedure);

db.As<ICloneable>().Verify(c => c.Clone(), Times.Once());
db2.Verify(d => d.CreateCommand(), Times.Once());
db2.Verify(d => d.Open(), Times.Once());
}
}

[TestMethod]
public void Quotes_With_Custom_Value_When_Set_Via_String()
{
using (GlobalSettings.UseTestInstance())
{
GlobalSettings.Instance.SetObjectQuoteStyle("(", "*");
var db = new Mock<IDbConnection>();
var db2 = new Mock<IDbConnection>();

db.As<ICloneable>().Setup(c => c.Clone()).Returns(db2.Object);

var cmd = new Mock<IDbCommand>();
cmd.SetupAllProperties();

db2.Setup(d => d.CreateCommand()).Returns(cmd.Object);

IDbConnection outConn;
var res = db.Object.CreateCommand("foo", "bar", 20, out outConn);

outConn.Should().NotBeNull();
res.Should().NotBeNull();
res.CommandText.Should().Be("(foo*.(bar*");
res.CommandTimeout.Should().Be(20);
res.CommandType.Should().Be(CommandType.StoredProcedure);

db.As<ICloneable>().Verify(c => c.Clone(), Times.Once());
db2.Verify(d => d.CreateCommand(), Times.Once());
db2.Verify(d => d.Open(), Times.Once());
}
}
}
}
}

0 comments on commit 8b59b41

Please sign in to comment.