Skip to content

Commit c885cce

Browse files
committed
NH-3467 - Add support of 2-args variant of LOCATE function
1 parent 07a0387 commit c885cce

File tree

4 files changed

+76
-38
lines changed

4 files changed

+76
-38
lines changed

src/NHibernate.Test/Hql/HQLFunctions.cs

Lines changed: 34 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ static HQLFunctions()
1818
notSupportedStandardFunction =
1919
new Hashtable
2020
{
21-
{"locate", new[] {typeof (FirebirdDialect), typeof (PostgreSQLDialect), typeof (SQLiteDialect)}},
21+
{"locate", new[] {typeof (SQLiteDialect)}},
2222
{"bit_length", new[] {typeof (SQLiteDialect)}},
2323
{"extract", new[] {typeof (SQLiteDialect)}},
2424
{"nullif", new[] {typeof (Oracle8iDialect)}}
@@ -83,12 +83,12 @@ public void AggregateCount()
8383
Assert.AreEqual(2, result);
8484

8585
// Count in where
86-
if (TestDialect.SupportsHavingWithoutGroupBy)
87-
{
88-
result = s.CreateQuery("select count(a.id) from Animal a having count(a.id)>1").UniqueResult();
89-
Assert.AreEqual(typeof (long), result.GetType());
90-
Assert.AreEqual(2, result);
91-
}
86+
if (TestDialect.SupportsHavingWithoutGroupBy)
87+
{
88+
result = s.CreateQuery("select count(a.id) from Animal a having count(a.id)>1").UniqueResult();
89+
Assert.AreEqual(typeof (long), result.GetType());
90+
Assert.AreEqual(2, result);
91+
}
9292
}
9393
}
9494

@@ -111,12 +111,12 @@ public void AggregateAvg()
111111
Assert.AreEqual(15D, result);
112112

113113
// In where
114-
if (TestDialect.SupportsHavingWithoutGroupBy)
115-
{
116-
result = s.CreateQuery("select avg(a.BodyWeight) from Animal a having avg(a.BodyWeight)>0").UniqueResult();
117-
Assert.AreEqual(typeof(double), result.GetType());
118-
Assert.AreEqual(15D, result);
119-
}
114+
if (TestDialect.SupportsHavingWithoutGroupBy)
115+
{
116+
result = s.CreateQuery("select avg(a.BodyWeight) from Animal a having avg(a.BodyWeight)>0").UniqueResult();
117+
Assert.AreEqual(typeof(double), result.GetType());
118+
Assert.AreEqual(15D, result);
119+
}
120120
}
121121
}
122122

@@ -137,12 +137,12 @@ public void AggregateMax()
137137
Assert.AreEqual(typeof(float), result.GetType()); //use column type
138138
Assert.AreEqual(20F, result);
139139

140-
if (TestDialect.SupportsHavingWithoutGroupBy)
141-
{
142-
result = s.CreateQuery("select max(a.BodyWeight) from Animal a having max(a.BodyWeight)>0").UniqueResult();
143-
Assert.AreEqual(typeof(float), result.GetType()); //use column type
144-
Assert.AreEqual(20F, result);
145-
}
140+
if (TestDialect.SupportsHavingWithoutGroupBy)
141+
{
142+
result = s.CreateQuery("select max(a.BodyWeight) from Animal a having max(a.BodyWeight)>0").UniqueResult();
143+
Assert.AreEqual(typeof(float), result.GetType()); //use column type
144+
Assert.AreEqual(20F, result);
145+
}
146146
}
147147
}
148148

@@ -163,12 +163,12 @@ public void AggregateMin()
163163
Assert.AreEqual(typeof(float), result.GetType()); //use column type
164164
Assert.AreEqual(10F, result);
165165

166-
if (TestDialect.SupportsHavingWithoutGroupBy)
167-
{
168-
result = s.CreateQuery("select min(a.BodyWeight) from Animal a having min(a.BodyWeight)>0").UniqueResult();
169-
Assert.AreEqual(typeof(float), result.GetType()); //use column type
170-
Assert.AreEqual(10F, result);
171-
}
166+
if (TestDialect.SupportsHavingWithoutGroupBy)
167+
{
168+
result = s.CreateQuery("select min(a.BodyWeight) from Animal a having min(a.BodyWeight)>0").UniqueResult();
169+
Assert.AreEqual(typeof(float), result.GetType()); //use column type
170+
Assert.AreEqual(10F, result);
171+
}
172172
}
173173
}
174174

@@ -189,12 +189,12 @@ public void AggregateSum()
189189
Assert.AreEqual(typeof(double), result.GetType());
190190
Assert.AreEqual(30D, result);
191191

192-
if (TestDialect.SupportsHavingWithoutGroupBy)
193-
{
194-
result = s.CreateQuery("select sum(a.BodyWeight) from Animal a having sum(a.BodyWeight)>0").UniqueResult();
195-
Assert.AreEqual(typeof(double), result.GetType());
196-
Assert.AreEqual(30D, result);
197-
}
192+
if (TestDialect.SupportsHavingWithoutGroupBy)
193+
{
194+
result = s.CreateQuery("select sum(a.BodyWeight) from Animal a having sum(a.BodyWeight)>0").UniqueResult();
195+
Assert.AreEqual(typeof(double), result.GetType());
196+
Assert.AreEqual(30D, result);
197+
}
198198
}
199199
}
200200

@@ -261,9 +261,9 @@ public void SubStringTwoParameters()
261261
{
262262
hql = "from Animal a where substring(concat(a.Description, ?), :start) = 'deffoo'";
263263
result = (Animal) s.CreateQuery(hql)
264-
.SetParameter(0, "foo")
265-
.SetParameter("start", 4)
266-
.UniqueResult();
264+
.SetParameter(0, "foo")
265+
.SetParameter("start", 4)
266+
.UniqueResult();
267267
Assert.AreEqual("abcdef", result.Description);
268268
}
269269
}

src/NHibernate/Dialect/Dialect.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ protected Dialect()
8585

8686
// standard sql92 functions (can be overridden by subclasses)
8787
RegisterFunction("substring", new AnsiSubstringFunction());
88-
RegisterFunction("locate", new SQLFunctionTemplate(NHibernateUtil.Int32, "locate(?1, ?2, ?3)"));
88+
RegisterFunction("locate", new StandardSQLFunction("locate", NHibernateUtil.Int32));
8989
RegisterFunction("trim", new AnsiTrimFunction());
9090
RegisterFunction("length", new StandardSQLFunction("length", NHibernateUtil.Int32));
9191
RegisterFunction("bit_length", new StandardSQLFunction("bit_length", NHibernateUtil.Int32));

src/NHibernate/Dialect/FirebirdDialect.cs

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ public FirebirdDialect()
121121
RegisterFunction("strlen", new StandardSQLFunction("strlen", NHibernateUtil.Int16));
122122
RegisterFunction("substr", new StandardSQLFunction("substr"));
123123
RegisterFunction("substrlen", new StandardSQLFunction("substrlen", NHibernateUtil.Int16));
124-
RegisterFunction("locate", new SQLFunctionTemplate(NHibernateUtil.Int32, "position(?1, ?2, cast(?3 as int))")); // The cast is needed, at least in the case that ?3 is a named integer parameter, otherwise firebird will generate an error. We have a unit test to cover this potential firebird bug.
124+
RegisterFunction("locate", new PositionFunction());
125125
RegisterFunction("replace", new StandardSafeSQLFunction("replace", NHibernateUtil.String, 3));
126126
//BLOB Functions
127127
RegisterFunction("string2blob", new StandardSQLFunction("string2blob"));
@@ -146,7 +146,6 @@ public override string AddColumnString
146146
get { return "add"; }
147147
}
148148

149-
150149
public override string GetSelectSequenceNextValString(string sequenceName)
151150
{
152151
return string.Format("gen_id({0}, 1 )", sequenceName);
@@ -283,5 +282,45 @@ public override string SelectGUIDString
283282
{
284283
get { return "select GEN_UUID() from RDB$DATABASE"; }
285284
}
285+
286+
[Serializable]
287+
private class PositionFunction : ISQLFunction
288+
{
289+
// The cast is needed, at least in the case that ?3 is a named integer parameter, otherwise firebird will generate an error.
290+
// We have a unit test to cover this potential firebird bug.
291+
private static readonly ISQLFunction LocateWith2Params = new StandardSQLFunction("position", NHibernateUtil.Int32);
292+
293+
private static readonly ISQLFunction LocateWith3Params = new SQLFunctionTemplate(NHibernateUtil.Int32,
294+
"position(?1, ?2, cast(?3 as int))");
295+
296+
public IType ReturnType(IType columnType, IMapping mapping)
297+
{
298+
return NHibernateUtil.Int32;
299+
}
300+
301+
public bool HasArguments
302+
{
303+
get { return true; }
304+
}
305+
306+
public bool HasParenthesesIfNoArguments
307+
{
308+
get { return true; }
309+
}
310+
311+
public SqlString Render(IList args, ISessionFactoryImplementor factory)
312+
{
313+
if (args.Count == 2)
314+
{
315+
return LocateWith2Params.Render(args, factory);
316+
}
317+
if (args.Count == 3)
318+
{
319+
return LocateWith3Params.Render(args, factory);
320+
}
321+
322+
throw new QueryException("'postition' function takes 2 or 3 arguments");
323+
}
324+
}
286325
}
287326
}

src/NHibernate/Dialect/Oracle8iDialect.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,6 @@ protected virtual void RegisterFunctions()
205205

206206
RegisterFunction("locate", new LocateFunction());
207207
RegisterFunction("substring", new StandardSQLFunction("substr", NHibernateUtil.String));
208-
RegisterFunction("locate", new SQLFunctionTemplate(NHibernateUtil.Int32, "instr(?2,?1)"));
209208
RegisterFunction("bit_length", new SQLFunctionTemplate(NHibernateUtil.Int32, "vsize(?1)*8"));
210209
RegisterFunction("coalesce", new NvlFunction());
211210

0 commit comments

Comments
 (0)