Skip to content

Commit 4c595d8

Browse files
committed
Escaped queries - Improves testing and fixes issue with strings having both escaped and non-escaped identifiers
1 parent 32b0f28 commit 4c595d8

4 files changed

Lines changed: 29 additions & 8 deletions

File tree

QueryBuilder.Tests/GeneralTests.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,16 @@ public void Raw_WrapIdentifiers()
123123
Assert.Equal("SELECT \"Id\", \"Name\", \"Age\" FROM \"Users\"", c[EngineCodes.PostgreSql]);
124124
Assert.Equal("SELECT \"Id\", \"Name\", \"Age\" FROM \"USERS\"", c[EngineCodes.Firebird]);
125125
}
126+
127+
[Fact]
128+
public void Raw_WrapIdentifiers_Escaped()
129+
{
130+
var query = new Query("Users").SelectRaw("'\\{1,2,3\\}'::int\\[\\]");
131+
132+
var c = Compile(query);
133+
134+
Assert.Equal("SELECT '{1,2,3}'::int[] FROM \"Users\"", c[EngineCodes.PostgreSql]);
135+
}
126136

127137
[Fact]
128138
public void WrapWithSpace()

QueryBuilder.Tests/HelperTests.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -226,9 +226,9 @@ public void ExpandParameters()
226226
}
227227

228228
[Theory]
229-
[InlineData(@"ANY('\{1,2,3,4,5\}')", @"\", "{", "[", @"ANY('\{1,2,3,4,5\}')")]
230-
[InlineData(@"ANY('{1,2,3,4,5}')", @"\", "{", "[", @"ANY('[1,2,3,4,5}')")]
231-
public void ReplaceIdentifierUnlessEscaped(string input, string escapeCharacter, string identifier, string newIdentifier, string expected)
229+
[InlineData(@"\{ text {", @"\", "{", "[", "{ text [")]
230+
[InlineData(@"{ text {", @"\", "{", "[", "[ text [")]
231+
public void WrapIdentifiers(string input, string escapeCharacter, string identifier, string newIdentifier, string expected)
232232
{
233233
var result = input.ReplaceIdentifierUnlessEscaped(escapeCharacter, identifier, newIdentifier);
234234
Assert.Equal(expected, result);

QueryBuilder.Tests/SelectTests.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -619,5 +619,15 @@ public void JoinTypes(string given, string output)
619619
$"SELECT * FROM \"USERS\" \n{output} \"COUNTRIES\" ON \"COUNTRIES\".\"ID\" = \"USERS\".\"COUNTRY_ID\"",
620620
c[EngineCodes.Firebird]);
621621
}
622+
623+
[Fact]
624+
public void OrWhereRawEscaped()
625+
{
626+
var query = new Query("Table").WhereRaw("[MyCol] = ANY(?::int\\[\\])", "{1,2,3}");
627+
628+
var c = Compile(query);
629+
630+
Assert.Equal("SELECT * FROM \"Table\" WHERE \"MyCol\" = ANY('{1,2,3}'::int[])", c[EngineCodes.PostgreSql]);
631+
}
622632
}
623633
}

QueryBuilder/Helper.cs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -161,12 +161,13 @@ public static IEnumerable<string> Repeat(this string str, int count)
161161

162162
public static string ReplaceIdentifierUnlessEscaped(this string input, string escapeCharacter, string identifier, string newIdentifier)
163163
{
164+
//Replace standard, non-escaped identifiers first
164165
var nonEscapedRegex = new Regex($@"(?<!{Regex.Escape(escapeCharacter)}){Regex.Escape(identifier)}");
165-
if (nonEscapedRegex.IsMatch(identifier))
166-
{
167-
return nonEscapedRegex.Replace(input, newIdentifier);
168-
}
169-
return input.Replace(escapeCharacter + identifier, newIdentifier);
166+
var nonEscapedReplace = nonEscapedRegex.Replace(input, newIdentifier);
167+
168+
//Then replace escaped identifiers, by just removing the escape character
169+
var escapedRegex = new Regex($@"{Regex.Escape(escapeCharacter)}{Regex.Escape(identifier)}");
170+
return escapedRegex.Replace(nonEscapedReplace, identifier);
170171
}
171172
}
172173
}

0 commit comments

Comments
 (0)