Skip to content

Commit

Permalink
Add an extension method ExecuteScript() to execute a SQL script.
Browse files Browse the repository at this point in the history
  • Loading branch information
GillesTourreau committed Oct 2, 2024
1 parent 7622a25 commit 758f901
Show file tree
Hide file tree
Showing 5 changed files with 213 additions and 5 deletions.
24 changes: 19 additions & 5 deletions src/Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,25 @@
<PackageReadmeFile>README.md</PackageReadmeFile>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<PackageReleaseNotes>
1.0.1
- Fix the documentation

1.0.0
- Initial version
2.1.0
- PosInformatique.Testing.Databases.SqlServer target the .NET Standard 2.0 platform.
- PosInformatique.Testing.Databases.SqlServer.Dac target the .NET Core 6.0 and .NET Framework 4.6.2
- PosInformatique.Testing.Databases.SqlServer.EntityFramework target the .NET Core 6.0
- Reduce the dependencies to Entity Framework 6.0
- Reduce the dependencies of DACfx to a more earlier version.
- Add new method SqlServerDatabase.ExecuteScript() to execute T-SQL script.

2.0.0
- Add SqlServerDatabaseComparer class to perform comparison between two databases.
- Add new PosInformatique.Testing.Databases.SqlServer.Dac NuGet package which contains DAC package tools.
- Add new SqlServer.CreateDatabaseAsync() extension method to create a database from a DbContext.
- Reduce dependencies version of the Entity Framework Core and SQL Server Client NuGet packages.

1.0.1
- Fix the documentation

1.0.0
- Initial version
</PackageReleaseNotes>
</PropertyGroup>

Expand Down
34 changes: 34 additions & 0 deletions src/Testing.Databases.SqlServer/SqlServerDatabaseExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,40 @@ [sys].[identity_columns] AS [ic]
database.ExecuteNonQuery("EXEC sp_msforeachtable 'ALTER TABLE ? WITH CHECK CHECK CONSTRAINT all'");
}

/// <summary>
/// Execute an T-SQL script on the <paramref name="database"/>.
/// </summary>
/// <param name="database"><see cref="SqlServerDatabase"/> where the <paramref name="script"/> will be executed.</param>
/// <param name="script">T-SQL script to execute.</param>
public static void ExecuteScript(this SqlServerDatabase database, string script)
{
using var stringReader = new StringReader(script);

ExecuteScript(database, stringReader);
}

/// <summary>
/// Execute an T-SQL script on the <paramref name="database"/>.
/// </summary>
/// <param name="database"><see cref="SqlServerDatabase"/> where the <paramref name="script"/> will be executed.</param>
/// <param name="script"><see cref="StringReader"/> which contains the T-SQL script to execute.</param>
public static void ExecuteScript(this SqlServerDatabase database, StringReader script)
{
var parser = new SqlServerScriptParser(script);

var block = parser.ReadNextBlock();

while (block is not null)
{
for (var i = 0; i < block.Count; i++)
{
database.ExecuteNonQuery(block.Code);
}

block = parser.ReadNextBlock();
}
}

private sealed class SqlInsertStatementBuilder
{
private readonly string tableName;
Expand Down
21 changes: 21 additions & 0 deletions src/Testing.Databases.SqlServer/SqlServerScriptBlock.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//-----------------------------------------------------------------------
// <copyright file="SqlServerScriptBlock.cs" company="P.O.S Informatique">
// Copyright (c) P.O.S Informatique. All rights reserved.
// </copyright>
//-----------------------------------------------------------------------

namespace PosInformatique.Testing.Databases.SqlServer
{
internal class SqlServerScriptBlock
{
public SqlServerScriptBlock(string code, int count)
{
this.Code = code;
this.Count = count;
}

public string Code { get; }

public int Count { get; }
}
}
73 changes: 73 additions & 0 deletions src/Testing.Databases.SqlServer/SqlServerScriptParser.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
//-----------------------------------------------------------------------
// <copyright file="SqlServerScriptParser.cs" company="P.O.S Informatique">
// Copyright (c) P.O.S Informatique. All rights reserved.
// </copyright>
//-----------------------------------------------------------------------

namespace PosInformatique.Testing.Databases.SqlServer
{
using System.Globalization;
using System.Text;

internal sealed class SqlServerScriptParser
{
private readonly TextReader script;

private bool isEndOfScript;

public SqlServerScriptParser(TextReader script)
{
this.script = script;
}

public SqlServerScriptBlock? ReadNextBlock()
{
if (this.isEndOfScript)
{
return null;
}

var codeBuilder = new StringBuilder();

var count = 1;

while (true)
{
var line = this.script.ReadLine();

if (line is null)
{
// End of the script reach.
this.isEndOfScript = true;
break;
}

line = line.Trim();

if (line.StartsWith("GO"))
{
// Parse the number after the "GO".
var textAfterGo = line.Substring(2).Trim();

if (textAfterGo != string.Empty)
{
count = Convert.ToInt32(textAfterGo, CultureInfo.InvariantCulture);
}

// If no code parsed, we continue to parse the block.
if (codeBuilder.Length == 0)
{
continue;
}

// Else, we stop the read of the script.
break;
}

codeBuilder.AppendLine(line);
}

return new SqlServerScriptBlock(codeBuilder.ToString(), count);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -90,5 +90,71 @@ Binary VARBINARY(MAX) NULL,
table.Rows[1]["Boolean"].As<bool>().Should().Be(false);
table.Rows[1]["BooleanNull"].Should().Be(DBNull.Value);
}

[Fact]
public void ExecuteScript_String()
{
var server = new SqlServer(ConnectionString);

var database = server.CreateEmptyDatabase("SqlServerDatabaseExtensionsTest");

database.ExecuteScript(@"
CREATE TABLE TableTest
(
Id INT NOT NULL
)
GO
GO
INSERT INTO [TableTest] ([Id]) VALUES (0)
GO
UPDATE [TableTest]
SET [Id] = [Id] + 1
GO 10
");

var table = database.ExecuteQuery("SELECT * FROM [TableTest]");

table.Rows.Should().HaveCount(1);

table.Rows[0]["Id"].Should().Be(10);
}

[Fact]
public void ExecuteScript_StringReader()
{
var server = new SqlServer(ConnectionString);

var database = server.CreateEmptyDatabase("SqlServerDatabaseExtensionsTest");

database.ExecuteScript(new StringReader(@"
CREATE TABLE TableTest
(
Id INT NOT NULL
)
GO
GO
INSERT INTO [TableTest] ([Id]) VALUES (0)
GO
UPDATE [TableTest]
SET [Id] = [Id] + 1
GO 10
"));

var table = database.ExecuteQuery("SELECT * FROM [TableTest]");

table.Rows.Should().HaveCount(1);

table.Rows[0]["Id"].Should().Be(10);
}
}
}

0 comments on commit 758f901

Please sign in to comment.