generated from Avanade/avanade-template
-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathDatabaseWildcard.cs
123 lines (104 loc) · 6.28 KB
/
DatabaseWildcard.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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
// Copyright (c) Avanade. Licensed under the MIT License. See https://github.com/Avanade/CoreEx
using CoreEx.Entities;
using CoreEx.Wildcards;
using System;
using System.Collections.Generic;
using System.Text;
namespace CoreEx.Database
{
/// <summary>
/// Provides database <see cref="Wildcards.Wildcard"/> capabilities.
/// </summary>
public class DatabaseWildcard
{
/// <summary>
/// Gets the default database multi (zero or more) wildcard character.
/// </summary>
public const char MultiWildcardCharacter = '%';
/// <summary>
/// Gets the default database single wildcard character.
/// </summary>
public const char SingleWildcardCharacter = '_';
/// <summary>
/// Gets the default list of characters that are to be escaped.
/// </summary>
/// <remarks>See <see href="https://docs.microsoft.com/en-us/sql/t-sql/language-elements/like-transact-sql"/> for more detail on escape characters.</remarks>
public static readonly char[] DefaultCharactersToEscape = ['%', '_', '['];
/// <summary>
/// Gets the default escaping format string when one of the <see cref="CharactersToEscape"/> is found.
/// </summary>
public const string DefaultEscapeFormat = "[{0}]";
/// <summary>
/// Initializes a new instance of the <see cref="DatabaseWildcard"/> class.
/// </summary>
/// <param name="wildcard">The <see cref="Wildcards.Wildcard"/> configuration.</param>
/// <param name="multiWildcard">The database multi (zero or more) wildcard character.</param>
/// <param name="singleWildcard">The database single wildcard character.</param>
/// <param name="charactersToEscape">The list of characters that are to be escaped (defaults to <see cref="DefaultCharactersToEscape"/>).</param>
/// <param name="escapeFormat">The escaping format string when one of the <see cref="CharactersToEscape"/> is found (defaults to <see cref="DefaultEscapeFormat"/>).</param>
#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Somehow the compiler thinks CharactersToEscape can be null; so not true.
public DatabaseWildcard(Wildcard? wildcard = null, char multiWildcard = MultiWildcardCharacter, char singleWildcard = SingleWildcardCharacter, char[]? charactersToEscape = null, string? escapeFormat = null)
#pragma warning restore CS8618
{
Wildcard = wildcard ?? Wildcard.Default ?? Wildcard.MultiBasic;
MultiWildcard = multiWildcard;
SingleWildcard = singleWildcard;
CharactersToEscape = new List<char>(charactersToEscape ?? DefaultCharactersToEscape);
EscapeFormat = escapeFormat ?? DefaultEscapeFormat;
if (MultiWildcard != char.MinValue && SingleWildcard != char.MinValue && MultiWildcard == SingleWildcard)
throw new ArgumentException("A Wildcard cannot be configured with the same character for the MultiWildcard and SingleWildcard.", nameof(multiWildcard));
if (Wildcard.Supported.HasFlag(WildcardSelection.MultiWildcard) && multiWildcard == char.MinValue)
throw new ArgumentException("A Wildcard that supports MultiWildcard must also define the database MultiWildcard character.");
if (Wildcard.Supported.HasFlag(WildcardSelection.SingleWildcard) && singleWildcard == char.MinValue)
throw new ArgumentException("A Wildcard that supports SingleWildcard must also define the database SingleWildcard character.");
if (CharactersToEscape != null && CharactersToEscape.Count > 0 && string.IsNullOrEmpty(EscapeFormat))
throw new InvalidOperationException("The EscapeFormat must be provided where CharactersToEscape have been defined.");
}
/// <summary>
/// Gets or sets the underlying <see cref="Wildcards.Wildcard"/> configuration.
/// </summary>
public Wildcard Wildcard { get; }
/// <summary>
/// Gets or sets the database multi (zero or more) wildcard character.
/// </summary>
public char MultiWildcard { get; }
/// <summary>
/// Gets or sets the database single wildcard character.
/// </summary>
public char SingleWildcard { get; }
/// <summary>
/// Gets or sets the list of characters that are to be escaped.
/// </summary>
public List<char> CharactersToEscape { get; }
/// <summary>
/// Gets or sets the escaping format when one of the <see cref="CharactersToEscape"/> is found.
/// </summary>
/// <remarks>See <see href="https://docs.microsoft.com/en-us/sql/t-sql/language-elements/like-transact-sql"/> for more detail on escape characters.</remarks>
public string EscapeFormat { get; }
/// <summary>
/// Replaces the wildcard text with the appropriate database representative characters to enable the corresponding SQL LIKE wildcard.
/// </summary>
/// <param name="text">The wildcard text.</param>
/// <returns>The SQL LIKE wildcard.</returns>
public string? Replace(string? text)
{
var wc = Wildcard ?? Wildcard.Default ?? Wildcard.MultiBasic;
var wr = wc.Parse(text).ThrowOnError();
if (wr.Selection.HasFlag(WildcardSelection.None) || (wr.Selection.HasFlag(WildcardSelection.Single) && wr.Selection.HasFlag(WildcardSelection.MultiWildcard)))
return new string(MultiWildcard, 1);
var sb = new StringBuilder();
foreach (var c in wr.Text!)
{
if (wr.Selection.HasFlag(WildcardSelection.MultiWildcard) && c == Wildcard.MultiWildcardCharacter)
sb.Append(MultiWildcard);
else if (wr.Selection.HasFlag(WildcardSelection.SingleWildcard) && c == Wildcard.SingleWildcardCharacter)
sb.Append(SingleWildcard);
else if (CharactersToEscape != null && CharactersToEscape.Contains(c))
sb.Append(string.Format(System.Globalization.CultureInfo.InvariantCulture, EscapeFormat, c));
else
sb.Append(c);
}
return Cleaner.Clean(sb.ToString(), StringTrim.None, wc.Transform);
}
}
}