Skip to content

Commit a5f67e2

Browse files
Merge branch 'master' of github.com:sqlkata/querybuilder
2 parents 828421f + 957a6ff commit a5f67e2

File tree

13 files changed

+101
-26
lines changed

13 files changed

+101
-26
lines changed

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: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,5 +224,14 @@ public void ExpandParameters()
224224

225225
Assert.Equal("where id = ? or id in (?,?) or id in ()", expanded);
226226
}
227+
228+
[Theory]
229+
[InlineData(@"\{ text {", @"\", "{", "[", "{ text [")]
230+
[InlineData(@"{ text {", @"\", "{", "[", "[ text [")]
231+
public void WrapIdentifiers(string input, string escapeCharacter, string identifier, string newIdentifier, string expected)
232+
{
233+
var result = input.ReplaceIdentifierUnlessEscaped(escapeCharacter, identifier, newIdentifier);
234+
Assert.Equal(expected, result);
235+
}
227236
}
228237
}

QueryBuilder.Tests/InsertTests.cs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using System.Linq;
23
using SqlKata.Compilers;
34
using SqlKata.Tests.Infrastructure;
45
using Xunit;
@@ -113,5 +114,25 @@ public void InsertWithEmptyString()
113114
"INSERT INTO \"BOOKS\" (\"ID\", \"AUTHOR\", \"ISBN\", \"DESCRIPTION\") VALUES (1, 'Author 1', '123456', '')",
114115
c[EngineCodes.Firebird]);
115116
}
117+
118+
[Fact]
119+
public void InsertWithByteArray()
120+
{
121+
var fauxImagebytes = new byte[] {0x1, 0x3, 0x3, 0x7};
122+
var query = new Query("Books")
123+
.AsInsert(new[]{"Id", "CoverImageBytes"},
124+
new object[]
125+
{
126+
1,
127+
fauxImagebytes
128+
});
129+
130+
var c = Compilers.Compile(query);
131+
Assert.All(c.Values, a => Assert.Equal(2, a.NamedBindings.Count));
132+
133+
var exemplar = c[EngineCodes.SqlServer];
134+
Assert.Equal("INSERT INTO [Books] ([Id], [CoverImageBytes]) VALUES (?, ?)", exemplar.RawSql);
135+
Assert.Equal("INSERT INTO [Books] ([Id], [CoverImageBytes]) VALUES (@p0, @p1)", exemplar.Sql);
136+
}
116137
}
117138
}

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/Compilers/Compiler.Conditions.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ protected virtual string CompileBasicDateCondition(SqlResult ctx, BasicDateCondi
134134
{
135135
var column = Wrap(x.Column);
136136

137-
var sql = $"{x.Part.ToUpper()}({column}) {checkOperator(x.Operator)} {Parameter(ctx, x.Value)}";
137+
var sql = $"{x.Part.ToUpperInvariant()}({column}) {checkOperator(x.Operator)} {Parameter(ctx, x.Value)}";
138138

139139
return x.IsNot
140140
? $"NOT ({sql})"

QueryBuilder/Compilers/Compiler.cs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ public partial class Compiler
1515
protected virtual string ColumnAsKeyword { get; set; } = "AS ";
1616
protected virtual string TableAsKeyword { get; set; } = "AS ";
1717
protected virtual string LastId { get; set; } = "";
18+
protected virtual string EscapeCharacter { get; set; } = "\\";
1819

1920
protected Compiler()
2021
{
@@ -446,7 +447,7 @@ protected virtual string CompileColumns(SqlResult ctx)
446447
sql = "DISTINCT " + sql;
447448
}
448449

449-
return "SELECT " + aggregate.Type.ToUpper() + "(" + sql + $") {ColumnAsKeyword}" + WrapValue(aggregate.Type);
450+
return "SELECT " + aggregate.Type.ToUpperInvariant() + "(" + sql + $") {ColumnAsKeyword}" + WrapValue(aggregate.Type);
450451
}
451452

452453
return "SELECT 1";
@@ -482,7 +483,7 @@ public virtual string CompileUnion(SqlResult ctx)
482483
{
483484
if (clause is Combine combineClause)
484485
{
485-
var combineOperator = combineClause.Operation.ToUpper() + " " + (combineClause.All ? "ALL " : "");
486+
var combineOperator = combineClause.Operation.ToUpperInvariant() + " " + (combineClause.All ? "ALL " : "");
486487

487488
var subCtx = CompileSelectQuery(combineClause.Query);
488489

@@ -809,12 +810,11 @@ public virtual string WrapIdentifiers(string input)
809810
return input
810811

811812
// deprecated
812-
.Replace("{", this.OpeningIdentifier)
813-
.Replace("}", this.ClosingIdentifier)
813+
.ReplaceIdentifierUnlessEscaped(this.EscapeCharacter,"{", this.OpeningIdentifier)
814+
.ReplaceIdentifierUnlessEscaped(this.EscapeCharacter,"}", this.ClosingIdentifier)
814815

815-
.Replace("[", this.OpeningIdentifier)
816-
.Replace("]", this.ClosingIdentifier);
816+
.ReplaceIdentifierUnlessEscaped(this.EscapeCharacter,"[", this.OpeningIdentifier)
817+
.ReplaceIdentifierUnlessEscaped(this.EscapeCharacter,"]", this.ClosingIdentifier);
817818
}
818-
819819
}
820820
}

QueryBuilder/Compilers/FirebirdCompiler.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ public override string CompileUnion(SqlResult ctx)
6060
{
6161
if (clause is Combine combineClause)
6262
{
63-
var combineOperator = combineClause.Operation.ToUpper() + " " + (combineClause.All ? "ALL " : "");
63+
var combineOperator = combineClause.Operation.ToUpperInvariant() + " " + (combineClause.All ? "ALL " : "");
6464

6565
var subCtx = CompileSelectQuery(combineClause.Query);
6666

@@ -125,7 +125,7 @@ protected override string CompileBasicDateCondition(SqlResult ctx, BasicDateCond
125125
}
126126
else
127127
{
128-
left = $"EXTRACT({condition.Part.ToUpper()} FROM {column})";
128+
left = $"EXTRACT({condition.Part.ToUpperInvariant()} FROM {column})";
129129
}
130130

131131
var sql = $"{left} {condition.Operator} {Parameter(ctx, condition.Value)}";
@@ -140,7 +140,7 @@ protected override string CompileBasicDateCondition(SqlResult ctx, BasicDateCond
140140

141141
public override string WrapValue(string value)
142142
{
143-
return base.WrapValue(value).ToUpper();
143+
return base.WrapValue(value).ToUpperInvariant();
144144
}
145145

146146
public override string CompileTrue()

QueryBuilder/Compilers/PostgresCompiler.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ public class PostgresCompiler : Compiler
44
{
55
public PostgresCompiler()
66
{
7-
LastId = "SELECT lastval()";
7+
LastId = "SELECT lastval() AS id";
88
}
99

1010
public override string EngineCode { get; } = EngineCodes.PostgreSql;
@@ -25,7 +25,7 @@ protected override string CompileBasicDateCondition(SqlResult ctx, BasicDateCond
2525
}
2626
else
2727
{
28-
left = $"DATE_PART('{condition.Part.ToUpper()}', {column})";
28+
left = $"DATE_PART('{condition.Part.ToUpperInvariant()}', {column})";
2929
}
3030

3131
var sql = $"{left} {condition.Operator} {Parameter(ctx, condition.Value)}";
@@ -38,4 +38,4 @@ protected override string CompileBasicDateCondition(SqlResult ctx, BasicDateCond
3838
return sql;
3939
}
4040
}
41-
}
41+
}

QueryBuilder/Compilers/SqlServerCompiler.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -146,17 +146,17 @@ public override string CompileFalse()
146146
protected override string CompileBasicDateCondition(SqlResult ctx, BasicDateCondition condition)
147147
{
148148
var column = Wrap(condition.Column);
149-
var part = condition.Part.ToUpper();
149+
var part = condition.Part.ToUpperInvariant();
150150

151151
string left;
152152

153153
if (part == "TIME" || part == "DATE")
154154
{
155-
left = $"CAST({column} AS {part.ToUpper()})";
155+
left = $"CAST({column} AS {part.ToUpperInvariant()})";
156156
}
157157
else
158158
{
159-
left = $"DATEPART({part.ToUpper()}, {column})";
159+
left = $"DATEPART({part.ToUpperInvariant()}, {column})";
160160
}
161161

162162
var sql = $"{left} {condition.Operator} {Parameter(ctx, condition.Value)}";

QueryBuilder/Helper.cs

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
using System.Collections;
33
using System.Collections.Generic;
44
using System.Linq;
5-
using System.Reflection;
65
using System.Text.RegularExpressions;
76

87
namespace SqlKata
@@ -11,7 +10,12 @@ public static class Helper
1110
{
1211
public static bool IsArray(object value)
1312
{
14-
if (value is string)
13+
if(value is string)
14+
{
15+
return false;
16+
}
17+
18+
if (value is byte[])
1519
{
1620
return false;
1721
}
@@ -154,5 +158,16 @@ public static IEnumerable<string> Repeat(this string str, int count)
154158
{
155159
return Enumerable.Repeat(str, count);
156160
}
161+
162+
public static string ReplaceIdentifierUnlessEscaped(this string input, string escapeCharacter, string identifier, string newIdentifier)
163+
{
164+
//Replace standard, non-escaped identifiers first
165+
var nonEscapedRegex = new Regex($@"(?<!{Regex.Escape(escapeCharacter)}){Regex.Escape(identifier)}");
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);
171+
}
157172
}
158173
}

0 commit comments

Comments
 (0)