Skip to content

Commit c4c711d

Browse files
authored
Improve path rule handling with reserved words in Hql.g (#3384)
Avoids handled exception when parsing queries with reserved words in path.
1 parent f38a6fd commit c4c711d

File tree

5 files changed

+85
-3
lines changed

5 files changed

+85
-3
lines changed
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
using Antlr.Runtime;
2+
using NHibernate.Hql.Ast.ANTLR;
3+
using NHibernate.Hql.Ast.ANTLR.Tree;
4+
using NUnit.Framework;
5+
6+
namespace NHibernate.Test.Hql.Parser
7+
{
8+
[TestFixture]
9+
public class HqlParserFixture
10+
{
11+
[Test]
12+
public void HandlesPathWithReservedWords()
13+
{
14+
Assert.DoesNotThrow(() => Parse("delete from System.Object"));
15+
Assert.DoesNotThrow(() => Parse("delete from Object.Object.Object.Object"));
16+
}
17+
18+
private static void Parse(string hql)
19+
{
20+
var lex = new HqlLexer(new CaseInsensitiveStringStream(hql));
21+
var tokens = new CommonTokenStream(lex);
22+
23+
var parser = new HqlParser(tokens)
24+
{
25+
TreeAdaptor = new ASTTreeAdaptor(),
26+
ParseErrorHandler = new WarningAsErrorReporter()
27+
}.statement();
28+
}
29+
}
30+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
using Antlr.Runtime;
2+
using NHibernate.Hql.Ast.ANTLR;
3+
4+
namespace NHibernate.Test.Hql.Parser
5+
{
6+
public class WarningAsErrorReporter : IParseErrorHandler
7+
{
8+
public void ReportError(RecognitionException e)
9+
{
10+
throw e;
11+
}
12+
13+
public void ReportError(string s)
14+
{
15+
throw new QueryException(s);
16+
}
17+
18+
public void ReportWarning(string s)
19+
{
20+
throw new QueryException(s);
21+
}
22+
23+
public int GetErrorCount() => 0;
24+
25+
public void ThrowQueryException()
26+
{
27+
}
28+
}
29+
}

src/NHibernate.Test/NHibernate.Test.csproj

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@
4646
<Compile Remove="**\NHSpecificTest\NH3121\**" />
4747
</ItemGroup>
4848
<ItemGroup>
49+
<Compile Include="..\NHibernate\Hql\Ast\ANTLR\CaseInsensitiveStringStream.cs">
50+
<Link>Hql\Parser\CaseInsensitiveStringStream.cs</Link>
51+
</Compile>
4952
<Compile Include="..\NHibernate\Util\AsyncReaderWriterLock.cs">
5053
<Link>UtilityTest\AsyncReaderWriterLock.cs</Link>
5154
</Compile>

src/NHibernate/Hql/Ast/ANTLR/Hql.g

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -695,10 +695,9 @@ constant
695695
696696
path
697697
@init {
698-
// TODO - need to clean up DotIdent - suspect that DotIdent2 supersedes the other one, but need to do the analysis
699-
//HandleDotIdent2();
698+
HandleDotIdents();
700699
}
701-
: identifier ( DOT^ { WeakKeywords(); } identifier )*
700+
: identifier ( DOT^ identifier )*
702701
;
703702
704703
// Wraps the IDENT token from the lexer, in order to provide

src/NHibernate/Hql/Ast/ANTLR/HqlParser.cs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,27 @@ protected override object RecoverFromMismatchedToken(IIntStream input, int ttype
112112
throw new MismatchedTokenException(ttype, input);
113113
}
114114

115+
public void HandleDotIdents()
116+
{
117+
int i = 2;
118+
119+
while (input.LA(i) == DOT)
120+
{
121+
var next = input.LT(i + 1);
122+
if (next != null)
123+
next.Type = IDENT;
124+
i += 2;
125+
}
126+
127+
if (input.LA(1) == IDENT || input.LA(2) != DOT)
128+
return;
129+
130+
if (IsPossibleId(input.LT(1)))
131+
{
132+
input.LT(1).Type = IDENT;
133+
}
134+
}
135+
115136
public void WeakKeywords()
116137
{
117138
int t = input.LA(1);

0 commit comments

Comments
 (0)