Skip to content

Commit dbdbd69

Browse files
committed
Merge pull request #414 from lnu/OracleLimitBug
NH-3767 - Wrong aliases when querying a table with the name starting with Select, From or As in Oracle
2 parents a362827 + 80d44ae commit dbdbd69

File tree

4 files changed

+118
-7
lines changed

4 files changed

+118
-7
lines changed
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
using NHibernate.Dialect;
2+
using NHibernate.SqlCommand;
3+
using NUnit.Framework;
4+
5+
namespace NHibernate.Test.DialectTest
6+
{
7+
[TestFixture]
8+
public class Oracle8iDialectFixture
9+
{
10+
#region Limit only
11+
[Test]
12+
public void GetLimitStringWithTableStartingWithSelectKeyword()
13+
{
14+
var dialect = new Oracle8iDialect();
15+
var sqlString=new SqlString(@"select selectlimi0_.""Id"" as column1_2_,selectlimi0_.""FirstName"" as column2_2_,selectlimi0_.""LastName"" as column3_2_ from ""SelectLimit"" selectlimi0_");
16+
var expected = new SqlString(@"select column1_2_,column2_2_,column3_2_ from ( select selectlimi0_.""Id"" as column1_2_,selectlimi0_.""FirstName"" as column2_2_,selectlimi0_.""LastName"" as column3_2_ from ""SelectLimit"" selectlimi0_ ) where rownum <=1");
17+
var limited=dialect.GetLimitString(sqlString, null, new SqlString("1"));
18+
Assert.AreEqual(limited, expected);
19+
}
20+
21+
[Test]
22+
public void GetLimitStringWithTableNotStartingWithSelectKeyword()
23+
{
24+
var dialect = new Oracle8iDialect();
25+
var sqlString = new SqlString(@"select eselectlimi0_.""Id"" as column1_2_,eselectlimi0_.""FirstName"" as column2_2_,eselectlimi0_.""LastName"" as column3_2_ from ""ESelectLimit"" eselectlimi0_");
26+
var expected = new SqlString(@"select column1_2_,column2_2_,column3_2_ from ( select eselectlimi0_.""Id"" as column1_2_,eselectlimi0_.""FirstName"" as column2_2_,eselectlimi0_.""LastName"" as column3_2_ from ""ESelectLimit"" eselectlimi0_ ) where rownum <=1");
27+
28+
var limited = dialect.GetLimitString(sqlString, null, new SqlString("1"));
29+
Assert.AreEqual(limited, expected);
30+
}
31+
32+
[Test]
33+
public void GetLimitStringWithTableStartingWithSelectKeywordAndDifferentCasing()
34+
{
35+
var dialect = new Oracle8iDialect();
36+
var sqlString = new SqlString(@"sElEct selectlimi0_.""Id"" as column1_2_,selectlimi0_.""FirstName"" as column2_2_,selectlimi0_.""LastName"" As column3_2_ fRom ""SelectLimit"" selectlimi0_");
37+
var expected = new SqlString(@"select column1_2_,column2_2_,column3_2_ from ( sElEct selectlimi0_.""Id"" as column1_2_,selectlimi0_.""FirstName"" as column2_2_,selectlimi0_.""LastName"" As column3_2_ fRom ""SelectLimit"" selectlimi0_ ) where rownum <=1");
38+
var limited = dialect.GetLimitString(sqlString, null, new SqlString("1"));
39+
Assert.AreEqual(limited, expected);
40+
}
41+
42+
[Test]
43+
public void GetLimitStringWithTableNotStartingWithSelectKeywordAndDifferentCasing()
44+
{
45+
var dialect = new Oracle8iDialect();
46+
var sqlString = new SqlString(@"sElEct eselectlimi0_.""Id"" as column1_2_,eselectlimi0_.""FirstName"" as column2_2_,eselectlimi0_.""LastName"" As column3_2_ fRom ""ESelectLimit"" eselectlimi0_");
47+
var expected = new SqlString(@"select column1_2_,column2_2_,column3_2_ from ( sElEct eselectlimi0_.""Id"" as column1_2_,eselectlimi0_.""FirstName"" as column2_2_,eselectlimi0_.""LastName"" As column3_2_ fRom ""ESelectLimit"" eselectlimi0_ ) where rownum <=1");
48+
49+
var limited = dialect.GetLimitString(sqlString, null, new SqlString("1"));
50+
Assert.AreEqual(limited, expected);
51+
}
52+
#endregion
53+
#region Offset And List
54+
[Test]
55+
public void GetLimitStringWithOffsetAndLimitAndTableStartingWithSelectKeyword()
56+
{
57+
var dialect = new Oracle8iDialect();
58+
var sqlString = new SqlString(@"select selectlimi0_.""Id"" as column1_2_,selectlimi0_.""FirstName"" as column2_2_,selectlimi0_.""LastName"" as column3_2_ from ""SelectLimit"" selectlimi0_");
59+
var expected = new SqlString(@"select column1_2_,column2_2_,column3_2_ from ( select row_.*, rownum rownum_ from ( select selectlimi0_.""Id"" as column1_2_,selectlimi0_.""FirstName"" as column2_2_,selectlimi0_.""LastName"" as column3_2_ from ""SelectLimit"" selectlimi0_ ) row_ where rownum <=1) where rownum_ >1");
60+
var limited = dialect.GetLimitString(sqlString, new SqlString("1"), new SqlString("1"));
61+
Assert.AreEqual(limited, expected);
62+
}
63+
64+
[Test]
65+
public void GetLimitStringWithOffsetAndLimitAndTableNotStartingWithSelectKeyword()
66+
{
67+
var dialect = new Oracle8iDialect();
68+
var sqlString = new SqlString(@"select eselectlimi0_.""Id"" as column1_2_,eselectlimi0_.""FirstName"" as column2_2_,eselectlimi0_.""LastName"" as column3_2_ from ""ESelectLimit"" eselectlimi0_");
69+
var expected = new SqlString(@"select column1_2_,column2_2_,column3_2_ from ( select row_.*, rownum rownum_ from ( select eselectlimi0_.""Id"" as column1_2_,eselectlimi0_.""FirstName"" as column2_2_,eselectlimi0_.""LastName"" as column3_2_ from ""ESelectLimit"" eselectlimi0_ ) row_ where rownum <=1) where rownum_ >1");
70+
71+
var limited = dialect.GetLimitString(sqlString, new SqlString("1"), new SqlString("1"));
72+
Assert.AreEqual(limited, expected);
73+
}
74+
75+
[Test]
76+
public void GetLimitStringWithOffsetAndLimitAndTableStartingWithSelectKeywordAndDifferentCasing()
77+
{
78+
var dialect = new Oracle8iDialect();
79+
var sqlString = new SqlString(@"sElEct selectlimi0_.""Id"" as column1_2_,selectlimi0_.""FirstName"" as column2_2_,selectlimi0_.""LastName"" As column3_2_ fRom ""SelectLimit"" selectlimi0_");
80+
var expected = new SqlString(@"select column1_2_,column2_2_,column3_2_ from ( select row_.*, rownum rownum_ from ( sElEct selectlimi0_.""Id"" as column1_2_,selectlimi0_.""FirstName"" as column2_2_,selectlimi0_.""LastName"" As column3_2_ fRom ""SelectLimit"" selectlimi0_ ) row_ where rownum <=1) where rownum_ >1");
81+
var limited = dialect.GetLimitString(sqlString, new SqlString("1"), new SqlString("1"));
82+
Assert.AreEqual(limited, expected);
83+
}
84+
85+
[Test]
86+
public void GetLimitStringWithOffsetAndLimitAndTableNotStartingWithSelectKeywordAndDifferentCasing()
87+
{
88+
var dialect = new Oracle8iDialect();
89+
var sqlString = new SqlString(@"sElEct eselectlimi0_.""Id"" as column1_2_,eselectlimi0_.""FirstName"" as column2_2_,eselectlimi0_.""LastName"" As column3_2_ fRom ""ESelectLimit"" eselectlimi0_");
90+
var expected = new SqlString(@"select column1_2_,column2_2_,column3_2_ from ( select row_.*, rownum rownum_ from ( sElEct eselectlimi0_.""Id"" as column1_2_,eselectlimi0_.""FirstName"" as column2_2_,eselectlimi0_.""LastName"" As column3_2_ fRom ""ESelectLimit"" eselectlimi0_ ) row_ where rownum <=1) where rownum_ >1");
91+
92+
var limited = dialect.GetLimitString(sqlString, new SqlString("1"), new SqlString("1"));
93+
Assert.AreEqual(limited, expected);
94+
}
95+
#endregion
96+
}
97+
}

src/NHibernate.Test/NHibernate.Test.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,7 @@
240240
<Compile Include="DialectTest\MsSql2012DialectFixture.cs" />
241241
<Compile Include="DialectTest\LockHintAppenderFixture.cs" />
242242
<Compile Include="DialectTest\MsSqlCe40DialectFixture.cs" />
243+
<Compile Include="DialectTest\Oracle8iDialectFixture.cs" />
243244
<Compile Include="DialectTest\SchemaTests\ColumnMetaDataFixture.cs" />
244245
<Compile Include="DriverTest\DbProviderFactoryDriveConnectionCommandProviderTest.cs" />
245246
<Compile Include="DriverTest\FirebirdClientDriverFixture.cs" />

src/NHibernate/Dialect/Dialect.cs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1162,23 +1162,23 @@ internal static void ExtractColumnOrAliasNames(SqlString select, out List<SqlStr
11621162

11631163
int nextTokenIndex = index += 1;
11641164

1165-
if (token.StartsWithCaseInsensitive("select"))
1165+
if (token.EqualsCaseInsensitive("select"))
11661166
continue;
11671167

1168-
if (token.StartsWithCaseInsensitive("distinct"))
1168+
if (token.EqualsCaseInsensitive("distinct"))
11691169
continue;
11701170

1171-
if (token.StartsWithCaseInsensitive(","))
1171+
if (token.EqualsCaseInsensitive(","))
11721172
continue;
11731173

1174-
if (token.StartsWithCaseInsensitive("from"))
1174+
if (token.EqualsCaseInsensitive("from"))
11751175
break;
11761176

11771177
// handle composite expressions like "2 * 4 as foo"
11781178
while ((nextTokenIndex < tokens.Count)
1179-
&& (tokens[nextTokenIndex].StartsWithCaseInsensitive("as") == false
1180-
&& tokens[nextTokenIndex].StartsWithCaseInsensitive("from") == false
1181-
&& tokens[nextTokenIndex].StartsWithCaseInsensitive(",") == false))
1179+
&& (tokens[nextTokenIndex].EqualsCaseInsensitive("as") == false
1180+
&& tokens[nextTokenIndex].EqualsCaseInsensitive("from") == false
1181+
&& tokens[nextTokenIndex].EqualsCaseInsensitive(",") == false))
11821182
{
11831183
SqlString nextToken = tokens[nextTokenIndex];
11841184
token = token.Append(nextToken);

src/NHibernate/SqlCommand/SqlString.cs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -609,6 +609,19 @@ public bool StartsWithCaseInsensitive(string value)
609609
&& IndexOf(value, 0, value.Length, StringComparison.InvariantCultureIgnoreCase) >= 0;
610610
}
611611

612+
/// <summary>
613+
/// Determines whether the sqlString matches the specified System.String,
614+
/// using case-insensitive comparison
615+
/// </summary>
616+
/// <param name="value">The System.String to match</param>
617+
/// <returns>true if the SqlString matches the value.</returns>
618+
public bool EqualsCaseInsensitive(string value)
619+
{
620+
return value != null
621+
&& value.Length == _length
622+
&& IndexOf(value, 0, value.Length, StringComparison.InvariantCultureIgnoreCase) >= 0;
623+
}
624+
612625
/// <summary>
613626
/// Retrieves a substring from this instance. The substring starts at a specified character position.
614627
/// </summary>

0 commit comments

Comments
 (0)