Skip to content

Commit 2947ffd

Browse files
author
jeffshumphreys@gmail.com
committed
Added new functions, cleaned up old functions.
1 parent d1867ec commit 2947ffd

File tree

6 files changed

+357
-29
lines changed

6 files changed

+357
-29
lines changed

MySQLCLRFunctions.csproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
<DefineConstants>DEBUG;TRACE</DefineConstants>
2323
<ErrorReport>prompt</ErrorReport>
2424
<WarningLevel>4</WarningLevel>
25+
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
2526
</PropertyGroup>
2627
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
2728
<DebugType>pdbonly</DebugType>
@@ -30,6 +31,7 @@
3031
<DefineConstants>TRACE</DefineConstants>
3132
<ErrorReport>prompt</ErrorReport>
3233
<WarningLevel>4</WarningLevel>
34+
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
3335
</PropertyGroup>
3436
<ItemGroup>
3537
<Reference Include="System" />
@@ -56,6 +58,8 @@
5658
<Compile Include="StringMeasure.cs" />
5759
<Compile Include="StringTest.cs" />
5860
<Compile Include="StringTransform.cs" />
61+
<Compile Include="StringTransformStripDownCustomizations.cs" />
62+
<Compile Include="StringTransformTSQLSpecific.cs" />
5963
<Compile Include="SuperClass.cs" />
6064
<Compile Include="Properties\AssemblyInfo.cs" />
6165
</ItemGroup>

StringTransform.cs

Lines changed: 111 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,14 @@
1313

1414
namespace MySQLCLRFunctions
1515
{
16+
/*
17+
*
18+
* Naming conventions for regex parameters
19+
* - find is for flat string
20+
* - regexmatchpattern when a matching process
21+
* - regexcapturepattern when it has to capture something
22+
* - match is a noun, what was matched to the pattern
23+
*/
1624
public static class StringTransform
1725
{
1826
/***************************************************************************************************************************************************************************************************
@@ -51,10 +59,10 @@ private static void FillRowWithCapStrs(Object matchObject, out SqlString match,
5159
*
5260
**************************************************************************************************************************************************************************************/
5361
[SqlFunction(DataAccess = DataAccessKind.None, IsDeterministic = true, IsPrecise = true, FillRowMethodName = "FillRowWithStrPieces")]
54-
public static IEnumerable Pieces(String stringtosplitintopieces, String regexsplitterpattern)
62+
public static IEnumerable Pieces(String stringtosplitintopieces, String regexmatchpattern)
5563
{
5664
returnpieceorderno = 1;
57-
string[] stringpieces = Regex.Split(stringtosplitintopieces, regexsplitterpattern, RegexOptions.IgnoreCase, TimeSpan.FromSeconds(2));
65+
string[] stringpieces = Regex.Split(stringtosplitintopieces, regexmatchpattern, RegexOptions.IgnoreCase, TimeSpan.FromSeconds(2));
5866
return stringpieces;
5967
}
6068

@@ -65,21 +73,111 @@ private static void FillRowWithStrPieces(Object obj, out SqlString piece, out Sq
6573
pieceorderNo = returnpieceorderno++;
6674
}
6775

76+
77+
// Extensions for internal use and simpler Fluent design, but not for SQL to call
78+
internal static string ReplaceMatchExt(this string input, string regexmatchpattern, string replacement)
79+
{
80+
return ReplaceMatch(input, regexmatchpattern, replacement);
81+
}
82+
83+
/***************************************************************************************************************************************************************************************************
84+
*
85+
* ReplaceMatch Similar to REPLACE in SQL Server, except it has .NET regex
86+
*
87+
* Note parameter naming convention: find is for flat string, regexmatchpattern when a matching process, regexcapturepattern when it has to capture something
88+
**************************************************************************************************************************************************************************************/
6889
[SqlFunction(DataAccess = DataAccessKind.None, IsDeterministic = true, IsPrecise = true)]
90+
public static string ReplaceMatch(string input, string regexmatchpattern, string replacement)
91+
{
92+
return Regex.Replace(input, regexmatchpattern, replacement);
93+
}
94+
95+
// Extensions for internal use and simpler Fluent design, but not for SQL to call
96+
internal unsafe static string ReplaceRecursiveExt(this string input, string find, string replacement)
97+
{
98+
return ReplaceRecursive(input, find, replacement);
99+
}
100+
101+
unsafe public static string ReplaceRecursive(string input, string find, string replacement)
102+
{
103+
if (find == replacement) return input;
104+
if (replacement.Contains(find))
105+
{
106+
throw new ArgumentOutOfRangeException(nameof(replacement), "the replacement string contains the sought string, so recursion would cause a blowup.");
107+
}
108+
109+
if (find.Length != replacement.Length)
110+
{
111+
StringBuilder sb = new StringBuilder(input);
112+
while (true)
113+
{
114+
int formersize = sb.Length;
115+
sb.Replace(find, replacement);
116+
int newsize = sb.Length;
117+
if (formersize == newsize)
118+
{
119+
return sb.ToString();
120+
}
121+
}
122+
}
123+
else if (find.Length == replacement.Length)
124+
{
125+
int findlen = find.Length;
126+
var findchars = find.ToCharArray();
127+
int len = input.Length;
128+
fixed (char* pointer = input)
129+
{
130+
// Add one to each of the characters.
131+
for (int i = 0; i <= len - findlen; i++)
132+
{
133+
int j2 = 0;
134+
for (int j = i; j < len; j++)
135+
{
136+
if (pointer[j + j2] != findchars[j2]) goto outerloop;
137+
j2++;
138+
if (j2 == findlen)
139+
{
140+
// Replace!!!!!!!!
141+
142+
pointer[j] = findchars[0];
143+
}
144+
}
145+
outerloop:
146+
;
147+
}
148+
// Return the mutated string.
149+
return new string(pointer);
150+
}
151+
}
152+
153+
return input;
154+
}
155+
69156
/***************************************************************************************************************************************************************************************************
70157
*
71158
* Trim repeating bunches of character off right of string
72159
*
73160
* - Created for trimming "1.3930000000" off floating point number in sql which REFUSES to round.
74161
*
75162
**************************************************************************************************************************************************************************************/
163+
[SqlFunction(DataAccess = DataAccessKind.None, IsDeterministic = true, IsPrecise = true)]
76164
public static string RTrimChar(string input, string trimAllOccFromRight)
77165
{
78166
if (input == null) return null;
79167
if (string.IsNullOrWhiteSpace(input)) return input;
80168
return input.TrimEnd(trimAllOccFromRight.ToCharArray());
81169
}
82170

171+
[SqlFunction(DataAccess = DataAccessKind.None, IsDeterministic = true, IsPrecise = true)]
172+
public static string RTrimN(string input, int howmanycharactersoffend)
173+
{
174+
if (input == null) return null;
175+
if (string.IsNullOrWhiteSpace(input) || howmanycharactersoffend == 0) return input;
176+
if (input.Length <= howmanycharactersoffend) return string.Empty;
177+
if (howmanycharactersoffend < 0) throw new ArgumentOutOfRangeException(nameof(howmanycharactersoffend), howmanycharactersoffend, "Cannot have negate remove characters.");
178+
return input.Substring(0, input.Length - howmanycharactersoffend);
179+
}
180+
83181
[SqlFunction(DataAccess = DataAccessKind.None, IsDeterministic = true, IsPrecise = true)]
84182
public static string LPad(string input, int padToLen)
85183
{
@@ -113,15 +211,19 @@ public static string BlankOut(string input, string blankanyofthese, string sep)
113211
}
114212
return input;
115213
}
214+
/***************************************************************************************************************************************************************************************************
215+
*
216+
* Title Like "UPPER" in SQL Server, as opposed to ToUpper in C#/.NET
217+
*
218+
**************************************************************************************************************************************************************************************/
116219
[SqlFunction(DataAccess = DataAccessKind.None, IsDeterministic = true, IsPrecise = true)]
117-
public static string RemoveSQLServerNameDelimiters(string input)
220+
public static string Title(string input)
118221
{
119-
if (string.IsNullOrWhiteSpace(input)) return input;
120-
if (string.IsNullOrEmpty(input)) return input;
121-
122-
input = input.Trim().Trim(new char[] { '[', ']' }).Replace("]]", "]");
123-
return input;
222+
return Regex.Replace(input, @"\b[a-z]\w+", delegate (Match match)
223+
{
224+
string v = match.ToString();
225+
return char.ToUpper(v[0]) + v.Substring(1);
226+
});
124227
}
125-
126228
}
127229
}
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
using Microsoft.SqlServer.Server;
2+
using System;
3+
using System.Collections.Generic;
4+
using System.Linq;
5+
using System.Runtime.CompilerServices;
6+
using System.Text;
7+
using System.Text.RegularExpressions;
8+
using System.Threading.Tasks;
9+
10+
namespace MySQLCLRFunctions
11+
{
12+
public static class StringTransformStripDownCustomizations
13+
{
14+
/***************************************************************************************************************************************************************************************************
15+
*
16+
* StripDownCherwellDescription Descriptions in Cherwell tickets are often full of garbage. Strip out garbage.
17+
*
18+
**************************************************************************************************************************************************************************************/
19+
[SqlFunction(DataAccess = DataAccessKind.None, IsDeterministic = true, IsPrecise = true)]
20+
public static string StripDownCherwellDescription(string input)
21+
{
22+
if (input == null) return null;
23+
if (string.IsNullOrWhiteSpace(input)) return input;
24+
return input.Trim();
25+
}
26+
}
27+
}
28+
/*
29+
*
30+
* using System;
31+
using System.Text;
32+
using System.Runtime.InteropServices;
33+
34+
class Class1
35+
{
36+
[DllImport("kernel32", SetLastError=true)]
37+
static extern unsafe uint GetWindowsDirectory(byte* lpBuffer,uint uSize);
38+
39+
static void Main(string[] args)
40+
{
41+
byte[] buff = new byte[512];
42+
unsafe
43+
{
44+
fixed(byte *pbuff=buff)GetWindowsDirectory(pbuff,512);
45+
}
46+
ASCIIEncoding ae = new ASCIIEncoding();
47+
System.Console.WriteLine(ae.GetString(buff));
48+
}
49+
}
50+
51+
unsafe public struct student
52+
{
53+
public fixed char Name[126];
54+
public fixed char Family[126];
55+
public int ID;
56+
public float mark;
57+
public student* next;
58+
59+
};
60+
public student* start;
61+
62+
63+
private void button1_Click(object sender, EventArgs e)
64+
{
65+
student m = new student();
66+
unsafe{
67+
if(start==null)
68+
{
69+
start = &m;
70+
start->Name[126] = textBox1.Text.ToCharArray();
71+
MessageBox.Show(Convert.ToString(start->Name));
72+
73+
74+
}
75+
76+
77+
78+
79+
}
80+
81+
82+
83+
*/

StringTransformTSQLSpecific.cs

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
using System;
2+
using System.Collections;
3+
using Microsoft.SqlServer.Server;
4+
using System.Data.SqlTypes;
5+
using System.Text.RegularExpressions;
6+
using System.Text;
7+
using System.Collections.Generic;
8+
9+
namespace MySQLCLRFunctions
10+
{
11+
public static class StringTransformTSQLSpecific
12+
{
13+
[SqlFunction(DataAccess = DataAccessKind.None, IsDeterministic = true, IsPrecise = true)]
14+
public static string RemoveSQLServerNameDelimiters(string input)
15+
{
16+
if (string.IsNullOrWhiteSpace(input)) return input;
17+
if (string.IsNullOrEmpty(input)) return input;
18+
19+
input = input.Trim().Trim(new char[] { '[', ']' }).Replace("]]", "]");
20+
return input;
21+
}
22+
23+
/// <summary>
24+
/// 'SELECT * FROM dbo.table where name = $3', 1, 'That''s my boy'
25+
/// </summary>
26+
/// <param name="sqlwithparametersembedded"></param>
27+
/// <param name="paramno"></param>
28+
/// <param name="newvalue"></param>
29+
/// <returns></returns>
30+
public static string ExpandSQLParameterString(string sqlwithparametersembedded, int paramno, string newvalue)
31+
{
32+
// https://docs.microsoft.com/en-us/dotnet/standard/base-types/character-escapes-in-regular-expressions
33+
newvalue = "'" + newvalue.Replace("'", "''") + "'";
34+
sqlwithparametersembedded = Regex.Replace(sqlwithparametersembedded, @"\$\d+(^\d|$)", newvalue);
35+
return sqlwithparametersembedded;
36+
}
37+
38+
/***************************************************************************************************************************************************************************************************
39+
*
40+
* StripDownSQLModule SQL Modules are hard to read as a single line with all the header junk.
41+
* Unsafe because uses pointers to improve performance the old fashioned C way for replacements that are 1 to 1 in length.
42+
*
43+
**************************************************************************************************************************************************************************************/
44+
[SqlFunction(DataAccess = DataAccessKind.None, IsDeterministic = true, IsPrecise = true)]
45+
public static string StripDownSQLModule(string input, bool toSingleLine, bool dropFullLineComments)
46+
{
47+
if (input == null) return null;
48+
if (string.IsNullOrWhiteSpace(input)) return input;
49+
input = input.ToLowerInvariant(); // We loose pretty, but matching is better
50+
input = input.Replace("\t", " ").Replace("[dbo].", "").Replace(" as ", " ").Replace("N'", "'");
51+
52+
input = StringTransform.ReplaceRecursive(input, " ", " ");
53+
var lines = input.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
54+
var cleanlines = new List<string>(100);
55+
56+
foreach (var line in lines)
57+
{
58+
if (Regex.IsMatch(line, "^--=+$")
59+
|| Regex.IsMatch(line, "^---+$")
60+
|| (dropFullLineComments && Regex.IsMatch(line.Trim(), "^--.*$")) // Dump comments
61+
|| line.Trim().Equals("set nocount on", StringComparison.CurrentCultureIgnoreCase)
62+
)
63+
64+
{
65+
// Discard
66+
}
67+
else
68+
{
69+
cleanlines.Add(line.TrimEnd(null));
70+
}
71+
}
72+
73+
if (toSingleLine)
74+
{
75+
var temps = String.Join(" ", cleanlines).ReplaceRecursiveExt(" ", " "); // After tabs newlines converted to spaces
76+
temps = temps.Replace(", ", ",").Replace(" =", "=").Replace("= ", "=").Replace(" (", "(").Replace("[", "").Replace("]", "").Replace(" begin ", "{")
77+
.Replace(" end ", "}").ReplaceMatchExt("\bend\b?$", "}");
78+
return temps;
79+
}
80+
return String.Join(Environment.NewLine, cleanlines);
81+
}
82+
}
83+
}

0 commit comments

Comments
 (0)