Skip to content

Commit e9455d3

Browse files
committed
HHH-19678 fix error reporting for JPA @orderby annotation
1 parent e1c6f49 commit e9455d3

File tree

13 files changed

+101
-77
lines changed

13 files changed

+101
-77
lines changed

hibernate-core/src/main/antlr/org/hibernate/grammars/ordering/OrderingLexer.g4

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,8 +137,31 @@ COMMA : ',';
137137
DOT : '.';
138138

139139
PLUS : '+';
140-
MINUS : '-';
140+
MINUS : '-';
141141
MULTIPLY : '*';
142142
DIVIDE : '/';
143143
MODULO : '%';
144144

145+
// Not used, but necessary for error reporting
146+
147+
EQUAL : '=';
148+
NOT_EQUAL : '!=' | '^=' | '<>';
149+
GREATER : '>';
150+
GREATER_EQUAL : '>=';
151+
LESS : '<';
152+
LESS_EQUAL : '<=';
153+
154+
LEFT_BRACKET : '[';
155+
RIGHT_BRACKET : ']';
156+
LEFT_BRACE : '{';
157+
RIGHT_BRACE : '}';
158+
AMPERSAND : '&';
159+
SEMICOLON : ';';
160+
COLON : ':';
161+
PIPE : '|';
162+
DOUBLE_PIPE : '||';
163+
QUESTION_MARK : '?';
164+
ARROW : '->';
165+
BANG: '!';
166+
AT: '@';
167+
HASH: '#';

hibernate-core/src/main/antlr/org/hibernate/grammars/ordering/OrderingParser.g4

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ package org.hibernate.grammars.ordering;
2323
// todo (6.0) : add hooks for keyword-as-identifier logging like we do for HQL?
2424

2525
orderByFragment
26-
: sortSpecification (COMMA sortSpecification)*
26+
: sortSpecification (COMMA sortSpecification)* EOF
2727
;
2828

2929
sortSpecification

hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/ManyToManyCollectionPart.java

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -123,16 +123,16 @@ public ModelPart findSubPart(String name, EntityMappingType targetType) {
123123
// to allow deferring the initialization of the target table group, omitting it if possible.
124124
// This is not possible for one-to-many associations because we need to create the target table group eagerly,
125125
// to preserve the cardinality. Also, the OneToManyTableGroup has no reference to the parent table group
126-
if ( getTargetKeyPropertyNames().contains( name ) ) {
126+
if ( foreignKey != null && getTargetKeyPropertyNames().contains( name ) ) {
127127
final ModelPart keyPart = foreignKey.getKeyPart();
128-
if ( keyPart instanceof EmbeddableValuedModelPart embeddableValuedModelPart
129-
&& keyPart instanceof VirtualModelPart ) {
130-
return embeddableValuedModelPart.findSubPart( name, targetType );
131-
}
132-
return keyPart;
128+
return keyPart instanceof EmbeddableValuedModelPart embeddableValuedModelPart
129+
&& keyPart instanceof VirtualModelPart
130+
? embeddableValuedModelPart.findSubPart( name, targetType )
131+
: keyPart;
132+
}
133+
else {
134+
return super.findSubPart( name, targetType );
133135
}
134-
135-
return super.findSubPart( name, targetType );
136136
}
137137

138138
@Override

hibernate-core/src/main/java/org/hibernate/metamodel/mapping/ordering/OrderByFragmentImpl.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,7 @@ public List<OrderingSpecification> getFragmentSpecs() {
2828
@Override
2929
public void apply(QuerySpec ast, TableGroup tableGroup, SqlAstCreationState creationState) {
3030
for ( int i = 0; i < fragmentSpecs.size(); i++ ) {
31-
final OrderingSpecification orderingSpec = fragmentSpecs.get( i );
32-
31+
final var orderingSpec = fragmentSpecs.get( i );
3332
orderingSpec.getExpression().apply(
3433
ast,
3534
tableGroup,

hibernate-core/src/main/java/org/hibernate/metamodel/mapping/ordering/OrderByFragmentTranslator.java

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,27 @@
44
*/
55
package org.hibernate.metamodel.mapping.ordering;
66

7+
import org.antlr.v4.runtime.ANTLRErrorListener;
8+
import org.antlr.v4.runtime.BaseErrorListener;
9+
import org.antlr.v4.runtime.CommonTokenStream;
10+
import org.antlr.v4.runtime.RecognitionException;
11+
import org.antlr.v4.runtime.Recognizer;
12+
import org.hibernate.QueryException;
713
import org.hibernate.grammars.ordering.OrderingLexer;
814
import org.hibernate.grammars.ordering.OrderingParser;
915
import org.hibernate.metamodel.mapping.PluralAttributeMapping;
1016
import org.hibernate.metamodel.mapping.ordering.ast.ParseTreeVisitor;
1117

1218

1319
import org.antlr.v4.runtime.BailErrorStrategy;
14-
import org.antlr.v4.runtime.BufferedTokenStream;
1520
import org.antlr.v4.runtime.CharStreams;
16-
import org.antlr.v4.runtime.ConsoleErrorListener;
1721
import org.antlr.v4.runtime.DefaultErrorStrategy;
1822
import org.antlr.v4.runtime.atn.PredictionMode;
1923
import org.antlr.v4.runtime.misc.ParseCancellationException;
24+
import org.hibernate.query.SyntaxException;
25+
import org.hibernate.query.sqm.ParsingException;
26+
27+
import static org.hibernate.query.hql.internal.StandardHqlTranslator.prettifyAntlrError;
2028

2129
/**
2230
* Responsible for performing the translation of the order-by fragment associated
@@ -46,11 +54,15 @@ public static OrderByFragment translate(
4654
return new OrderByFragmentImpl( visitor.visitOrderByFragment( parseTree ) );
4755
}
4856

57+
public static void check(String fragment) {
58+
final var parseTree = buildParseTree( fragment );
59+
// TODO: check against the model
60+
}
4961

5062
private static OrderingParser.OrderByFragmentContext buildParseTree(String fragment) {
5163
final var lexer = new OrderingLexer( CharStreams.fromString( fragment ) );
5264

53-
final var parser = new OrderingParser( new BufferedTokenStream( lexer ) );
65+
final var parser = new OrderingParser( new CommonTokenStream( lexer ) );
5466

5567
// try to use SLL(k)-based parsing first - it's faster
5668
parser.getInterpreter().setPredictionMode( PredictionMode.SLL );
@@ -67,11 +79,23 @@ private static OrderingParser.OrderByFragmentContext buildParseTree(String fragm
6779

6880
// fall back to LL(k)-based parsing
6981
parser.getInterpreter().setPredictionMode( PredictionMode.LL );
70-
parser.addErrorListener( ConsoleErrorListener.INSTANCE );
82+
// parser.addErrorListener( ConsoleErrorListener.INSTANCE );
7183
parser.setErrorHandler( new DefaultErrorStrategy() );
7284

85+
final ANTLRErrorListener errorListener = new BaseErrorListener() {
86+
@Override
87+
public void syntaxError(Recognizer<?, ?> recognizer, Object offendingSymbol, int line, int charPositionInLine, String msg, RecognitionException e) {
88+
throw new SyntaxException( prettifyAntlrError( offendingSymbol, line, charPositionInLine, msg, e, fragment, true ), fragment );
89+
}
90+
};
91+
parser.addErrorListener( errorListener );
92+
7393
return parser.orderByFragment();
7494
}
95+
catch ( ParsingException ex ) {
96+
// Note that this is supposed to represent a bug in the parser
97+
throw new QueryException( "Failed to interpret syntax [" + ex.getMessage() + "]", fragment, ex );
98+
}
7599
}
76100

77101
}

hibernate-core/src/main/java/org/hibernate/metamodel/mapping/ordering/ast/CollectionPartPath.java

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -57,14 +57,12 @@ public SequencePart resolvePathPart(
5757
String identifier,
5858
boolean isTerminal,
5959
TranslationContext translationContext) {
60-
if ( referencedPart instanceof ModelPartContainer ) {
61-
final ModelPart subPart = ( (ModelPartContainer) referencedPart ).findSubPart( name, null );
62-
60+
if ( referencedPart instanceof ModelPartContainer modelPartContainer ) {
61+
final ModelPart subPart = modelPartContainer.findSubPart( name, null );
6362
return new DomainPathContinuation( navigablePath.append( name ), this, subPart );
6463
}
65-
66-
throw new PathResolutionException(
67-
"Could not resolve order-by path : " + navigablePath + " -> " + name
68-
);
64+
else {
65+
throw new PathResolutionException( name );
66+
}
6967
}
7068
}

hibernate-core/src/main/java/org/hibernate/metamodel/mapping/ordering/ast/DomainPathContinuation.java

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
package org.hibernate.metamodel.mapping.ordering.ast;
66

77
import org.hibernate.metamodel.mapping.EmbeddableValuedModelPart;
8-
import org.hibernate.metamodel.mapping.EmbeddableMappingType;
98
import org.hibernate.metamodel.mapping.ModelPart;
109
import org.hibernate.metamodel.mapping.internal.AbstractDomainPath;
1110
import org.hibernate.metamodel.mapping.ordering.TranslationContext;
@@ -49,13 +48,11 @@ public SequencePart resolvePathPart(
4948
String identifier,
5049
boolean isTerminal,
5150
TranslationContext translationContext) {
52-
if ( referencedModelPart instanceof EmbeddableValuedModelPart ) {
53-
final EmbeddableMappingType embeddableMappingType = (EmbeddableMappingType) referencedModelPart.getPartMappingType();
51+
if ( referencedModelPart instanceof EmbeddableValuedModelPart embeddableValuedModelPart ) {
52+
final var embeddableMappingType = embeddableValuedModelPart.getEmbeddableTypeDescriptor();
5453
final ModelPart subPart = embeddableMappingType.findSubPart( name, null );
5554
if ( subPart == null ) {
56-
throw new PathResolutionException(
57-
"Could not resolve path token : " + referencedModelPart + " -> " + name
58-
);
55+
throw new PathResolutionException( name );
5956
}
6057

6158
return new DomainPathContinuation(
@@ -65,9 +62,6 @@ public SequencePart resolvePathPart(
6562
);
6663
}
6764

68-
throw new PathResolutionException(
69-
"Domain path of type `" + referencedModelPart.getPartMappingType() +
70-
"` -> `" + name + "`"
71-
);
65+
throw new PathResolutionException( name );
7266
}
7367
}

hibernate-core/src/main/java/org/hibernate/metamodel/mapping/ordering/ast/FkDomainPathContinuation.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ public SequencePart resolvePathPart(
4141
boolean isTerminal,
4242
TranslationContext translationContext) {
4343
if ( !possiblePaths.contains( name ) ) {
44-
throw new PathResolutionException( "Domain path of type `" + referencedModelPart.getPartMappingType() + "` -> `" + name + "`" );
44+
throw new PathResolutionException( name );
4545
}
4646

4747
final HashSet<String> furtherPaths = new HashSet<>();

hibernate-core/src/main/java/org/hibernate/metamodel/mapping/ordering/ast/PathConsumer.java

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,7 @@
66

77
import org.hibernate.metamodel.mapping.PluralAttributeMapping;
88
import org.hibernate.metamodel.mapping.ordering.TranslationContext;
9-
import org.hibernate.query.hql.internal.BasicDotIdentifierConsumer;
109

11-
import org.jboss.logging.Logger;
1210

1311
/**
1412
* Represents the translation of an individual part of a path in `@OrderBy` translation
@@ -52,7 +50,12 @@ public void consumeIdentifier(
5250
}
5351
pathSoFar.append( unquotedIdentifier );
5452

55-
currentPart = currentPart.resolvePathPart( unquotedIdentifier, identifier, isTerminal, translationContext );
53+
try {
54+
currentPart = currentPart.resolvePathPart( unquotedIdentifier, identifier, isTerminal, translationContext );
55+
}
56+
catch (PathResolutionException pre) {
57+
throw new PathResolutionException( "Unable to resolve path '" + pathSoFar + "'" );
58+
}
5659
}
5760

5861
private void reset() {

hibernate-core/src/main/java/org/hibernate/metamodel/mapping/ordering/ast/PathResolutionException.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,14 @@
55
package org.hibernate.metamodel.mapping.ordering.ast;
66

77
import org.hibernate.HibernateException;
8+
import org.hibernate.metamodel.mapping.NonTransientException;
89

910
/**
1011
* Indicates a problem resolving a domain-path occurring in an order-by fragment
1112
*
1213
* @author Steve Ebersole
1314
*/
14-
public class PathResolutionException extends HibernateException {
15+
public class PathResolutionException extends HibernateException implements NonTransientException {
1516
public PathResolutionException(String message) {
1617
super( message );
1718
}

0 commit comments

Comments
 (0)