Skip to content

Commit d01f8a8

Browse files
Avoid some superfluous parameter casts with Firebird
Fix #1886
1 parent b1b4fd9 commit d01f8a8

File tree

3 files changed

+166
-12
lines changed

3 files changed

+166
-12
lines changed

src/NHibernate.Test/Async/DriverTest/FirebirdClientDriverFixture.cs

Lines changed: 55 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -177,25 +177,76 @@ private DbCommand BuildInsertWithParamsInSelectCommand(SqlType paramType)
177177
private DbCommand BuildInsertWithParamsInSelectCommandWithSelectInColumnName(SqlType paramType)
178178
{
179179
var sqlString = new SqlStringBuilder()
180-
.Add("insert into table1 (col1_select_aaa) ")
180+
.Add("insert into table1 (col1_select_aaa, select_aaa, col1_select) ")
181181
.Add("values(")
182182
.AddParameter()
183+
.Add(", ")
184+
.AddParameter()
185+
.Add(", ")
186+
.AddParameter()
183187
.Add(") from table2")
184188
.ToSqlString();
185189

186-
return _driver.GenerateCommand(CommandType.Text, sqlString, new[] { paramType });
190+
return _driver.GenerateCommand(CommandType.Text, sqlString, new[] { paramType, paramType, paramType });
187191
}
188192

189193
private DbCommand BuildInsertWithParamsInSelectCommandWithWhereInColumnName(SqlType paramType)
190194
{
191195
var sqlString = new SqlStringBuilder()
192-
.Add("insert into table1 (col1_where_aaa) ")
196+
.Add("insert into table1 (col1_where_aaa, where_aaa, col1_where) ")
193197
.Add("values(")
194198
.AddParameter()
199+
.Add(", ")
200+
.AddParameter()
201+
.Add(", ")
202+
.AddParameter()
195203
.Add(") from table2")
196204
.ToSqlString();
197205

198-
return _driver.GenerateCommand(CommandType.Text, sqlString, new[] { paramType });
206+
return _driver.GenerateCommand(CommandType.Text, sqlString, new[] { paramType, paramType, paramType });
207+
}
208+
209+
private DbCommand BuildBetweenCommand(SqlType paramType)
210+
{
211+
var sqlString =
212+
new SqlStringBuilder()
213+
.Add("select col1 from table where col2 between ")
214+
.AddParameter()
215+
.Add(" and ")
216+
.AddParameter()
217+
.ToSqlString();
218+
219+
return _driver.GenerateCommand(CommandType.Text, sqlString, new[] { paramType, paramType });
220+
}
221+
222+
private DbCommand BuildPagingCommand(SqlType paramType)
223+
{
224+
var sqlString =
225+
new SqlStringBuilder()
226+
.Add("select first ")
227+
.AddParameter()
228+
.Add(" skip ")
229+
.AddParameter()
230+
.Add(" col1 from table")
231+
.ToSqlString();
232+
233+
return _driver.GenerateCommand(CommandType.Text, sqlString, new[] { paramType, paramType });
234+
}
235+
236+
private DbCommand BuildInCommand(SqlType paramType)
237+
{
238+
var sqlString =
239+
new SqlStringBuilder()
240+
.Add("select col1 from table where col2 in (")
241+
.AddParameter()
242+
.Add(", ")
243+
.AddParameter()
244+
.Add(", ")
245+
.AddParameter()
246+
.Add(")")
247+
.ToSqlString();
248+
249+
return _driver.GenerateCommand(CommandType.Text, sqlString, new[] { paramType, paramType });
199250
}
200251
}
201252
}

src/NHibernate.Test/DriverTest/FirebirdClientDriverFixture.cs

Lines changed: 93 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ public void AdjustCommand_InsertWithParamsInSelect_ParameterIsNotCasted_WhenColu
153153
{
154154
_driver.AdjustCommand(cmd);
155155

156-
var expected = "insert into table1 (col1_select_aaa) values(@p0) from table2";
156+
var expected = "insert into table1 (col1_select_aaa, select_aaa, col1_select) values(@p0, @p1, @p2) from table2";
157157
Assert.That(cmd.CommandText, Is.EqualTo(expected));
158158
}
159159
}
@@ -165,11 +165,47 @@ public void AdjustCommand_InsertWithParamsInSelect_ParameterIsNotCasted_WhenColu
165165
{
166166
_driver.AdjustCommand(cmd);
167167

168-
var expected = "insert into table1 (col1_where_aaa) values(@p0) from table2";
168+
var expected = "insert into table1 (col1_where_aaa, where_aaa, col1_where) values(@p0, @p1, @p2) from table2";
169169
Assert.That(cmd.CommandText, Is.EqualTo(expected));
170170
}
171171
}
172172

173+
[Test]
174+
public void AdjustCommand_ParameterWithinBetween_ParameterIsNotCasted()
175+
{
176+
using (var cmd = BuildBetweenCommand(SqlTypeFactory.GetString(255)))
177+
{
178+
var originalSql = cmd.CommandText;
179+
_driver.AdjustCommand(cmd);
180+
181+
Assert.That(cmd.CommandText, Is.EqualTo(originalSql));
182+
}
183+
}
184+
185+
[Test]
186+
public void AdjustCommand_ParameterWithinPaging_ParameterIsNotCasted()
187+
{
188+
using (var cmd = BuildPagingCommand(SqlTypeFactory.Int32))
189+
{
190+
var originalSql = cmd.CommandText;
191+
_driver.AdjustCommand(cmd);
192+
193+
Assert.That(cmd.CommandText, Is.EqualTo(originalSql));
194+
}
195+
}
196+
197+
[Test]
198+
public void AdjustCommand_ParameterWithinIn_ParameterIsNotCasted()
199+
{
200+
using (var cmd = BuildInCommand(SqlTypeFactory.GetString(255)))
201+
{
202+
var originalSql = cmd.CommandText;
203+
_driver.AdjustCommand(cmd);
204+
205+
Assert.That(cmd.CommandText, Is.EqualTo(originalSql));
206+
}
207+
}
208+
173209
private DbConnection MakeConnection()
174210
{
175211
var result = _driver.CreateConnection();
@@ -251,25 +287,76 @@ private DbCommand BuildInsertWithParamsInSelectCommand(SqlType paramType)
251287
private DbCommand BuildInsertWithParamsInSelectCommandWithSelectInColumnName(SqlType paramType)
252288
{
253289
var sqlString = new SqlStringBuilder()
254-
.Add("insert into table1 (col1_select_aaa) ")
290+
.Add("insert into table1 (col1_select_aaa, select_aaa, col1_select) ")
255291
.Add("values(")
256292
.AddParameter()
293+
.Add(", ")
294+
.AddParameter()
295+
.Add(", ")
296+
.AddParameter()
257297
.Add(") from table2")
258298
.ToSqlString();
259299

260-
return _driver.GenerateCommand(CommandType.Text, sqlString, new[] { paramType });
300+
return _driver.GenerateCommand(CommandType.Text, sqlString, new[] { paramType, paramType, paramType });
261301
}
262302

263303
private DbCommand BuildInsertWithParamsInSelectCommandWithWhereInColumnName(SqlType paramType)
264304
{
265305
var sqlString = new SqlStringBuilder()
266-
.Add("insert into table1 (col1_where_aaa) ")
306+
.Add("insert into table1 (col1_where_aaa, where_aaa, col1_where) ")
267307
.Add("values(")
268308
.AddParameter()
309+
.Add(", ")
310+
.AddParameter()
311+
.Add(", ")
312+
.AddParameter()
269313
.Add(") from table2")
270314
.ToSqlString();
271315

272-
return _driver.GenerateCommand(CommandType.Text, sqlString, new[] { paramType });
316+
return _driver.GenerateCommand(CommandType.Text, sqlString, new[] { paramType, paramType, paramType });
317+
}
318+
319+
private DbCommand BuildBetweenCommand(SqlType paramType)
320+
{
321+
var sqlString =
322+
new SqlStringBuilder()
323+
.Add("select col1 from table where col2 between ")
324+
.AddParameter()
325+
.Add(" and ")
326+
.AddParameter()
327+
.ToSqlString();
328+
329+
return _driver.GenerateCommand(CommandType.Text, sqlString, new[] { paramType, paramType });
330+
}
331+
332+
private DbCommand BuildPagingCommand(SqlType paramType)
333+
{
334+
var sqlString =
335+
new SqlStringBuilder()
336+
.Add("select first ")
337+
.AddParameter()
338+
.Add(" skip ")
339+
.AddParameter()
340+
.Add(" col1 from table")
341+
.ToSqlString();
342+
343+
return _driver.GenerateCommand(CommandType.Text, sqlString, new[] { paramType, paramType });
344+
}
345+
346+
private DbCommand BuildInCommand(SqlType paramType)
347+
{
348+
var sqlString =
349+
new SqlStringBuilder()
350+
.Add("select col1 from table where col2 in (")
351+
.AddParameter()
352+
.Add(", ")
353+
.AddParameter()
354+
.Add(", ")
355+
.AddParameter()
356+
.Add(")")
357+
.ToSqlString();
358+
359+
return _driver.GenerateCommand(CommandType.Text, sqlString, new[] { paramType, paramType });
273360
}
274361
}
275362
}

src/NHibernate/Driver/FirebirdClientDriver.cs

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,24 @@ namespace NHibernate.Driver
1818
/// </summary>
1919
public class FirebirdClientDriver : ReflectionBasedDriver
2020
{
21-
private const string SELECT_CLAUSE_EXP = @"(?<=\bselect|\bwhere).*";
22-
private const string CAST_PARAMS_EXP = @"(?<![=<>]\s?|first\s?|skip\s?|between\s|between\s@\bp\w+\b\sand\s)@\bp\w+\b(?!\s?[=<>])";
21+
private const string SELECT_CLAUSE_EXP = @"(?<=\bselect\b|\bwhere\b).*";
22+
private const string CAST_PARAMS_EXP =
23+
// Zero-width negative look-behind: the match must not be preceded by
24+
@"(?<!" +
25+
// a comparison,
26+
@"[=<>]\s*" +
27+
// or a paging instruction,
28+
@"|\bfirst\s+|\bskip\s+" +
29+
// or a "between" condition,
30+
@"|\bbetween\s+|\bbetween\s+@p\w+\s+and\s+" +
31+
// or a "in" condition.
32+
@"|\bin\s*\([@\w\s,]*)" +
33+
// Match a parameter
34+
@"@p\w+\b" +
35+
// Zero-width negative look-ahead: the match must not be followed by
36+
@"(?!" +
37+
// a comparison.
38+
@"\s*[=<>])";
2339
private static readonly Regex _statementRegEx = new Regex(SELECT_CLAUSE_EXP, RegexOptions.IgnoreCase);
2440
private static readonly Regex _castCandidateRegEx = new Regex(CAST_PARAMS_EXP, RegexOptions.IgnoreCase);
2541
private readonly FirebirdDialect _fbDialect = new FirebirdDialect();

0 commit comments

Comments
 (0)