-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathSqlClrAssemblyPreprocessor.cs
70 lines (59 loc) · 2.1 KB
/
SqlClrAssemblyPreprocessor.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
using System.Globalization;
using System.Text;
using System.Text.RegularExpressions;
using DbUp.Engine;
namespace Migratonator;
internal partial class SqlClrAssemblyPreprocessor : IScriptPreprocessor
{
public SqlClrAssemblyPreprocessor(string assemblySearchPath)
{
AssemblySearchPath = assemblySearchPath;
}
private string AssemblySearchPath { get; }
public string Process(string contents)
{
// look for variables in the script which denote the SQL CLR assembly
// to be loaded into the database. The variable is replaced with the
// the hex encoded contents of the assembly.
//
// the format of the variable is:
//
// %SqlCLRHex:AbsoluteOrRelativePathToAssembly%
//
foreach (Match match in SqlClrHexRegex().Matches(contents))
{
var path = match.Groups["path"].Value;
// construct full path
if (!Path.IsPathRooted(path))
path = Path.Combine(AssemblySearchPath, path);
if (File.Exists(path))
{
// HEX encode the contents of the assembly
var hexString = GetHexString(path);
contents = contents.Replace(match.Value, hexString);
}
else
{
throw new FileNotFoundException("SQL CLR Assembly not found", path);
}
}
return contents;
}
[GeneratedRegex("%SqlCLRHex:(?<path>[^%]+)%", RegexOptions.Multiline)]
private static partial Regex SqlClrHexRegex();
private static string GetHexString(string assemblyPath)
{
var builder = new StringBuilder();
builder.Append("0x");
using (var stream = new FileStream(assemblyPath, FileMode.Open, FileAccess.Read, FileShare.Read))
{
var currentByte = stream.ReadByte();
while (currentByte > -1)
{
builder.Append(currentByte.ToString("X2", CultureInfo.InvariantCulture));
currentByte = stream.ReadByte();
}
}
return builder.ToString();
}
}