batch of minor improvements to the parser/SemanticQueryBuilder (typesafety)

This commit is contained in:
Gavin King 2023-07-06 11:47:14 +02:00
parent 980bf4d8ab
commit 135871dbd9
2 changed files with 113 additions and 124 deletions

View File

@ -575,16 +575,26 @@ limitClause
* An 'offset' of the first query result to return * An 'offset' of the first query result to return
*/ */
offsetClause offsetClause
: OFFSET parameterOrIntegerLiteral (ROW | ROWS)? : OFFSET parameterOrIntegerLiteral
(ROW | ROWS)? // no semantics
; ;
/** /**
* A much more complex syntax for limits * A much more complex syntax for limits
*/ */
fetchClause fetchClause
: FETCH (FIRST | NEXT) (parameterOrIntegerLiteral | parameterOrNumberLiteral PERCENT) (ROW | ROWS) (ONLY | WITH TIES) : FETCH
(FIRST | NEXT) // no semantics
fetchCountOrPercent
(ROW | ROWS) // no semantics
(ONLY | WITH TIES)
; ;
fetchCountOrPercent
: parameterOrIntegerLiteral
| parameterOrNumberLiteral PERCENT
;
/** /**
* An parameterizable integer literal * An parameterizable integer literal
*/ */

View File

@ -83,7 +83,6 @@ import org.hibernate.query.sqm.LiteralNumberFormatException;
import org.hibernate.query.sqm.NodeBuilder; import org.hibernate.query.sqm.NodeBuilder;
import org.hibernate.query.sqm.ParsingException; import org.hibernate.query.sqm.ParsingException;
import org.hibernate.query.sqm.SetOperator; import org.hibernate.query.sqm.SetOperator;
import org.hibernate.query.SortDirection;
import org.hibernate.query.sqm.SqmExpressible; import org.hibernate.query.sqm.SqmExpressible;
import org.hibernate.query.sqm.SqmPathSource; import org.hibernate.query.sqm.SqmPathSource;
import org.hibernate.query.sqm.SqmQuerySource; import org.hibernate.query.sqm.SqmQuerySource;
@ -1096,7 +1095,7 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private void setOffsetFetchLimit(SqmQueryPart<?> sqmQueryPart, HqlParser.LimitClauseContext limitClauseContext, HqlParser.OffsetClauseContext offsetClauseContext, HqlParser.FetchClauseContext fetchClauseContext) { private void setOffsetFetchLimit(SqmQueryPart<?> sqmQueryPart, HqlParser.LimitClauseContext limitClauseContext, HqlParser.OffsetClauseContext offsetClauseContext, HqlParser.FetchClauseContext fetchClauseContext) {
// these casts are all fine because the parser only accepts literals and parameters // these casts are all fine because the parser only accepts literals and parameters
sqmQueryPart.setOffsetExpression((SqmExpression<? extends Number>) visitOffsetClause(offsetClauseContext)); sqmQueryPart.setOffsetExpression( (SqmExpression<? extends Number>) visitOffsetClause(offsetClauseContext) );
if ( limitClauseContext == null ) { if ( limitClauseContext == null ) {
sqmQueryPart.setFetchExpression( sqmQueryPart.setFetchExpression(
(SqmExpression<? extends Number>) visitFetchClause(fetchClauseContext), (SqmExpression<? extends Number>) visitFetchClause(fetchClauseContext),
@ -1600,47 +1599,24 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
HqlLogging.QUERY_LOGGER.debugf( "Questionable sorting by constant value : %s", sortExpression ); HqlLogging.QUERY_LOGGER.debugf( "Questionable sorting by constant value : %s", sortExpression );
} }
final SortDirection sortOrder; final SortDirection sortOrder =
ctx.sortDirection() == null || ctx.sortDirection().DESC() == null
? SortDirection.ASCENDING
: SortDirection.DESCENDING;
final NullPrecedence nullPrecedence; final NullPrecedence nullPrecedence;
int nextIndex = 1; if ( ctx.nullsPrecedence() == null ) {
if ( nextIndex < ctx.getChildCount() ) { nullPrecedence = NullPrecedence.NONE;
ParseTree parseTree = ctx.getChild( nextIndex );
if ( parseTree instanceof HqlParser.SortDirectionContext ) {
switch ( ( (TerminalNode) parseTree.getChild( 0 ) ).getSymbol().getType() ) {
case HqlParser.ASC:
sortOrder = SortDirection.ASCENDING;
break;
case HqlParser.DESC:
sortOrder = SortDirection.DESCENDING;
break;
default:
throw new ParsingException( "Unrecognized sort ordering: " + parseTree.getText() );
}
nextIndex++;
}
else {
sortOrder = SortDirection.ASCENDING;
}
parseTree = ctx.getChild( nextIndex );
if ( parseTree instanceof HqlParser.NullsPrecedenceContext ) {
switch ( ( (TerminalNode) parseTree.getChild( 1 ) ).getSymbol().getType() ) {
case HqlParser.FIRST:
nullPrecedence = NullPrecedence.FIRST;
break;
case HqlParser.LAST:
nullPrecedence = NullPrecedence.LAST;
break;
default:
throw new ParsingException( "Unrecognized null precedence: " + parseTree.getText() );
}
}
else {
nullPrecedence = NullPrecedence.NONE;
}
} }
else { else {
sortOrder = SortDirection.ASCENDING; if ( ctx.nullsPrecedence().FIRST() != null ) {
nullPrecedence = NullPrecedence.NONE; nullPrecedence = NullPrecedence.FIRST;
}
else if ( ctx.nullsPrecedence().LAST() != null ) {
nullPrecedence = NullPrecedence.LAST;
}
else {
throw new ParsingException( "Unrecognized null precedence" );
}
} }
return new SqmSortSpecification( sortExpression, sortOrder, nullPrecedence ); return new SqmSortSpecification( sortExpression, sortOrder, nullPrecedence );
@ -1682,7 +1658,7 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
return null; return null;
} }
return (SqmExpression<?>) ctx.getChild( 1 ).accept( this ); return (SqmExpression<?>) ctx.parameterOrIntegerLiteral().accept( this );
} }
@Override @Override
@ -1691,7 +1667,7 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
return null; return null;
} }
return (SqmExpression<?>) ctx.getChild( 1 ).accept( this ); return (SqmExpression<?>) ctx.parameterOrIntegerLiteral().accept( this );
} }
@Override @Override
@ -1700,26 +1676,30 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
return null; return null;
} }
return (SqmExpression<?>) ctx.getChild( 2 ).accept( this ); final HqlParser.FetchCountOrPercentContext fetchCountOrPercent = ctx.fetchCountOrPercent();
if ( fetchCountOrPercent.PERCENT() == null ) {
return (SqmExpression<?>) fetchCountOrPercent.parameterOrIntegerLiteral().accept( this );
}
else {
return (SqmExpression<?>) fetchCountOrPercent.parameterOrNumberLiteral().accept( this );
}
} }
private FetchClauseType visitFetchClauseType(HqlParser.FetchClauseContext ctx) { private FetchClauseType visitFetchClauseType(HqlParser.FetchClauseContext ctx) {
if ( ctx == null ) { if ( ctx == null ) {
return FetchClauseType.ROWS_ONLY; return FetchClauseType.ROWS_ONLY;
} }
final int thirdSymbolType = ( (TerminalNode) ctx.getChild( 3 ) ).getSymbol().getType(); else if ( ctx.fetchCountOrPercent().PERCENT() == null ) {
final int lastSymbolType = ( (TerminalNode) ctx.getChild( ctx.getChildCount() - 1 ) ).getSymbol().getType(); return ctx.TIES() == null ? FetchClauseType.ROWS_ONLY : FetchClauseType.ROWS_WITH_TIES;
if ( lastSymbolType == HqlParser.TIES ) {
return thirdSymbolType == HqlParser.PERCENT ? FetchClauseType.PERCENT_WITH_TIES : FetchClauseType.ROWS_WITH_TIES;
} }
else { else {
return thirdSymbolType == HqlParser.PERCENT ? FetchClauseType.PERCENT_ONLY : FetchClauseType.ROWS_ONLY; return ctx.TIES() == null ? FetchClauseType.PERCENT_ONLY : FetchClauseType.PERCENT_WITH_TIES;
} }
} }
@Override @Override
public Object visitSyntacticPathExpression(HqlParser.SyntacticPathExpressionContext ctx) { public Object visitSyntacticPathExpression(HqlParser.SyntacticPathExpressionContext ctx) {
SemanticPathPart part = visitSyntacticDomainPath( (HqlParser.SyntacticDomainPathContext) ctx.getChild( 0 ) ); SemanticPathPart part = visitSyntacticDomainPath( ctx.syntacticDomainPath() );
if ( ctx.getChildCount() == 2 ) { if ( ctx.getChildCount() == 2 ) {
dotIdentifierConsumerStack.push( dotIdentifierConsumerStack.push(
new BasicDotIdentifierConsumer( part, this ) { new BasicDotIdentifierConsumer( part, this ) {
@ -1729,7 +1709,7 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
} }
); );
try { try {
part = (SemanticPathPart) ctx.getChild( 1 ).accept( this ); part = (SemanticPathPart) ctx.pathContinuation().accept( this );
} }
finally { finally {
dotIdentifierConsumerStack.pop(); dotIdentifierConsumerStack.pop();
@ -1743,7 +1723,7 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
@Override @Override
public Object visitGeneralPathExpression(HqlParser.GeneralPathExpressionContext ctx) { public Object visitGeneralPathExpression(HqlParser.GeneralPathExpressionContext ctx) {
final SemanticPathPart part = visitGeneralPathFragment( (HqlParser.GeneralPathFragmentContext) ctx.getChild( 0 ) ); final SemanticPathPart part = visitGeneralPathFragment( ctx.generalPathFragment() );
if ( part instanceof DomainPathPart ) { if ( part instanceof DomainPathPart ) {
return ( (DomainPathPart) part ).getSqmExpression(); return ( (DomainPathPart) part ).getSqmExpression();
} }
@ -1752,16 +1732,17 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
@Override @Override
public SqmExpression<?> visitFunctionExpression(HqlParser.FunctionExpressionContext ctx) { public SqmExpression<?> visitFunctionExpression(HqlParser.FunctionExpressionContext ctx) {
return (SqmExpression<?>) ctx.getChild( 0 ).accept( this ); return (SqmExpression<?>) ctx.function().accept( this );
} }
@Override @Override
public SqmExpression<?> visitParameterOrIntegerLiteral(HqlParser.ParameterOrIntegerLiteralContext ctx) { public SqmExpression<?> visitParameterOrIntegerLiteral(HqlParser.ParameterOrIntegerLiteralContext ctx) {
final ParseTree firstChild = ctx.getChild( 0 ); if ( ctx.INTEGER_LITERAL() != null ) {
if ( firstChild instanceof TerminalNode ) { return integerLiteral( ctx.INTEGER_LITERAL().getText() );
return integerLiteral( firstChild.getText() ); }
else {
return (SqmExpression<?>) ctx.parameter().accept( this );
} }
return (SqmExpression<?>) firstChild.accept( this );
} }
@Override @Override
@ -2776,7 +2757,7 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
throw new UnsupportedOperationException( "Path continuation from `id()` reference not yet implemented" ); throw new UnsupportedOperationException( "Path continuation from `id()` reference not yet implemented" );
} }
final SqmPath<Object> sqmPath = consumeDomainPath( (HqlParser.PathContext) ctx.getChild( 2 ) ); final SqmPath<?> sqmPath = consumeDomainPath( (HqlParser.PathContext) ctx.getChild( 2 ) );
final DomainType<?> sqmPathType = sqmPath.getReferencedPathSource().getSqmPathType(); final DomainType<?> sqmPathType = sqmPath.getReferencedPathSource().getSqmPathType();
if ( sqmPathType instanceof IdentifiableDomainType<?> ) { if ( sqmPathType instanceof IdentifiableDomainType<?> ) {
@ -2799,7 +2780,7 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
@Override @Override
public SqmPath<?> visitEntityVersionReference(HqlParser.EntityVersionReferenceContext ctx) { public SqmPath<?> visitEntityVersionReference(HqlParser.EntityVersionReferenceContext ctx) {
final SqmPath<Object> sqmPath = consumeDomainPath( (HqlParser.PathContext) ctx.getChild( 2 ) ); final SqmPath<?> sqmPath = consumeDomainPath( (HqlParser.PathContext) ctx.getChild( 2 ) );
final DomainType<?> sqmPathType = sqmPath.getReferencedPathSource().getSqmPathType(); final DomainType<?> sqmPathType = sqmPath.getReferencedPathSource().getSqmPathType();
if ( sqmPathType instanceof IdentifiableDomainType<?> ) { if ( sqmPathType instanceof IdentifiableDomainType<?> ) {
@ -2830,7 +2811,7 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
@Override @Override
public SqmPath<?> visitEntityNaturalIdReference(HqlParser.EntityNaturalIdReferenceContext ctx) { public SqmPath<?> visitEntityNaturalIdReference(HqlParser.EntityNaturalIdReferenceContext ctx) {
final SqmPath<Object> sqmPath = consumeDomainPath( (HqlParser.PathContext) ctx.getChild( 2 ) ); final SqmPath<?> sqmPath = consumeDomainPath( (HqlParser.PathContext) ctx.getChild( 2 ) );
final DomainType<?> sqmPathType = sqmPath.getReferencedPathSource().getSqmPathType(); final DomainType<?> sqmPathType = sqmPath.getReferencedPathSource().getSqmPathType();
if ( sqmPathType instanceof IdentifiableDomainType<?> ) { if ( sqmPathType instanceof IdentifiableDomainType<?> ) {
@ -2873,7 +2854,7 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
@Override @Override
public SqmFkExpression<?> visitToOneFkReference(HqlParser.ToOneFkReferenceContext ctx) { public SqmFkExpression<?> visitToOneFkReference(HqlParser.ToOneFkReferenceContext ctx) {
final SqmPath<Object> sqmPath = consumeDomainPath( (HqlParser.PathContext) ctx.getChild( 2 ) ); final SqmPath<?> sqmPath = consumeDomainPath( (HqlParser.PathContext) ctx.getChild( 2 ) );
final SqmPathSource<?> toOneReference = sqmPath.getReferencedPathSource(); final SqmPathSource<?> toOneReference = sqmPath.getReferencedPathSource();
final boolean validToOneRef = toOneReference.getBindableType() == Bindable.BindableType.SINGULAR_ATTRIBUTE final boolean validToOneRef = toOneReference.getBindableType() == Bindable.BindableType.SINGULAR_ATTRIBUTE
@ -5023,7 +5004,7 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
final SqmPath<?> pluralPath = consumePluralAttributeReference( ctx.path() ); final SqmPath<?> pluralPath = consumePluralAttributeReference( ctx.path() );
if ( pluralPath instanceof SqmPluralValuedSimplePath ) { if ( pluralPath instanceof SqmPluralValuedSimplePath ) {
if ( isIndexedPluralAttribute( pluralPath ) ) { if ( isIndexedPluralAttribute( pluralPath ) ) {
return new SqmIndexAggregateFunction<>(pluralPath, functionName); return new SqmIndexAggregateFunction<>( pluralPath, functionName );
} }
else { else {
throw new FunctionArgumentException( "Path '" + ctx.path() throw new FunctionArgumentException( "Path '" + ctx.path()
@ -5056,7 +5037,7 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
@Override @Override
public SqmSubQuery<?> visitSubquery(HqlParser.SubqueryContext ctx) { public SqmSubQuery<?> visitSubquery(HqlParser.SubqueryContext ctx) {
final HqlParser.QueryExpressionContext queryExpressionContext = (HqlParser.QueryExpressionContext) ctx.getChild( 0 ); final HqlParser.QueryExpressionContext queryExpressionContext = ctx.queryExpression();
final SqmSubQuery<?> subQuery = new SqmSubQuery<>( final SqmSubQuery<?> subQuery = new SqmSubQuery<>(
processingStateStack.getCurrent().getProcessingQuery(), processingStateStack.getCurrent().getProcessingQuery(),
creationContext.getNodeBuilder() creationContext.getNodeBuilder()
@ -5091,10 +5072,13 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
@Override @Override
public SemanticPathPart visitPath(HqlParser.PathContext ctx) { public SemanticPathPart visitPath(HqlParser.PathContext ctx) {
final ParseTree firstChild = ctx.getChild( 0 ); final HqlParser.SyntacticDomainPathContext syntacticDomainPath = ctx.syntacticDomainPath();
if ( firstChild instanceof HqlParser.SyntacticDomainPathContext ) { final HqlParser.GeneralPathFragmentContext generalPathFragment = ctx.generalPathFragment();
final SemanticPathPart syntacticNavigablePathResult = visitSyntacticDomainPath( (HqlParser.SyntacticDomainPathContext) firstChild ); if ( syntacticDomainPath != null ) {
if ( ctx.getChildCount() == 2 ) { final SemanticPathPart syntacticNavigablePathResult =
visitSyntacticDomainPath(syntacticDomainPath);
final HqlParser.PathContinuationContext pathContinuation = ctx.pathContinuation();
if ( pathContinuation != null ) {
dotIdentifierConsumerStack.push( dotIdentifierConsumerStack.push(
new BasicDotIdentifierConsumer( syntacticNavigablePathResult, this ) { new BasicDotIdentifierConsumer( syntacticNavigablePathResult, this ) {
@Override @Override
@ -5103,7 +5087,7 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
} }
); );
try { try {
return (SemanticPathPart) ctx.getChild( 1 ).accept( this ); return (SemanticPathPart) pathContinuation.accept( this );
} }
finally { finally {
dotIdentifierConsumerStack.pop(); dotIdentifierConsumerStack.pop();
@ -5111,41 +5095,36 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
} }
return syntacticNavigablePathResult; return syntacticNavigablePathResult;
} }
else if ( firstChild instanceof HqlParser.GeneralPathFragmentContext ) { else if (generalPathFragment != null) {
return (SemanticPathPart) firstChild.accept( this ); return (SemanticPathPart) generalPathFragment.accept(this);
}
else {
throw new ParsingException("Illegal path '" + ctx.getText() + "'");
} }
throw new ParsingException( "Unrecognized `path` rule branch" );
} }
@Override @Override
public SemanticPathPart visitGeneralPathFragment(HqlParser.GeneralPathFragmentContext ctx) { public SemanticPathPart visitGeneralPathFragment(HqlParser.GeneralPathFragmentContext ctx) {
return visitIndexedPathAccessFragment( return visitIndexedPathAccessFragment( ctx.simplePath(), ctx.indexedPathAccessFragment() );
(HqlParser.SimplePathContext) ctx.getChild( 0 ),
ctx.getChildCount() == 1 ? null : (HqlParser.IndexedPathAccessFragmentContext) ctx.getChild( 1 )
);
} }
@Override @Override
public SemanticPathPart visitSyntacticDomainPath(HqlParser.SyntacticDomainPathContext ctx) { public SemanticPathPart visitSyntacticDomainPath(HqlParser.SyntacticDomainPathContext ctx) {
final ParseTree firstChild = ctx.getChild( 0 ); if ( ctx.treatedNavigablePath() != null ) {
if ( firstChild instanceof HqlParser.TreatedNavigablePathContext ) { return visitTreatedNavigablePath( ctx.treatedNavigablePath() );
return visitTreatedNavigablePath( (HqlParser.TreatedNavigablePathContext) firstChild );
} }
else if ( firstChild instanceof HqlParser.CollectionValueNavigablePathContext ) { else if ( ctx.collectionValueNavigablePath() != null ) {
return visitCollectionValueNavigablePath( (HqlParser.CollectionValueNavigablePathContext) firstChild ); return visitCollectionValueNavigablePath( ctx.collectionValueNavigablePath() );
} }
else if ( firstChild instanceof HqlParser.MapKeyNavigablePathContext ) { else if ( ctx.mapKeyNavigablePath() != null ) {
return visitMapKeyNavigablePath( (HqlParser.MapKeyNavigablePathContext) firstChild ); return visitMapKeyNavigablePath( ctx.mapKeyNavigablePath() );
} }
else if ( firstChild instanceof HqlParser.SimplePathContext && ctx.getChildCount() == 2 ) { else if ( ctx.simplePath() != null && ctx.indexedPathAccessFragment() != null ) {
return visitIndexedPathAccessFragment( return visitIndexedPathAccessFragment( ctx.simplePath(), ctx.indexedPathAccessFragment() );
(HqlParser.SimplePathContext) firstChild, }
(HqlParser.IndexedPathAccessFragmentContext) ctx.getChild( 1 ) else {
); throw new ParsingException( "Illegal domain path '" + ctx.getText() + "'" );
} }
throw new ParsingException( "Unsure how to process `syntacticDomainPath` over : " + ctx.getText() );
} }
private SemanticPathPart visitIndexedPathAccessFragment( private SemanticPathPart visitIndexedPathAccessFragment(
@ -5157,10 +5136,10 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
return pathPart; return pathPart;
} }
final SqmExpression<?> indexExpression = (SqmExpression<?>) idxCtx.getChild( 1 ).accept(this ); final SqmExpression<?> indexExpression = (SqmExpression<?>) idxCtx.expression().accept(this );
final boolean hasIndexContinuation = idxCtx.getChildCount() == 5; final boolean hasIndexContinuation = idxCtx.DOT() != null;
final SqmPath<?> indexedPath = pathPart.resolveIndexedAccess( indexExpression, !hasIndexContinuation, this ); final SqmPath<?> indexedPath =
pathPart.resolveIndexedAccess( indexExpression, !hasIndexContinuation, this );
if ( hasIndexContinuation ) { if ( hasIndexContinuation ) {
dotIdentifierConsumerStack.push( dotIdentifierConsumerStack.push(
new BasicDotIdentifierConsumer( indexedPath, this ) { new BasicDotIdentifierConsumer( indexedPath, this ) {
@ -5170,7 +5149,7 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
} }
); );
try { try {
return (SemanticPathPart) idxCtx.getChild( 4 ).accept( this ); return (SemanticPathPart) idxCtx.generalPathFragment().accept( this );
} }
finally { finally {
dotIdentifierConsumerStack.pop(); dotIdentifierConsumerStack.pop();
@ -5186,8 +5165,7 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
@Override @Override
public SemanticPathPart visitSimplePath(HqlParser.SimplePathContext ctx) { public SemanticPathPart visitSimplePath(HqlParser.SimplePathContext ctx) {
final int numberOfContinuations = ctx.getChildCount() - 1; final int numberOfContinuations = ctx.simplePathElement().size();
final boolean hasContinuations = numberOfContinuations != 0;
final DotIdentifierConsumer dotIdentifierConsumer = dotIdentifierConsumerStack.getCurrent(); final DotIdentifierConsumer dotIdentifierConsumer = dotIdentifierConsumerStack.getCurrent();
final HqlParser.IdentifierContext identifierContext = ctx.identifier(); final HqlParser.IdentifierContext identifierContext = ctx.identifier();
@ -5196,20 +5174,18 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
dotIdentifierConsumer.consumeIdentifier( dotIdentifierConsumer.consumeIdentifier(
visitIdentifier( identifierContext ), visitIdentifier( identifierContext ),
true, true,
! hasContinuations numberOfContinuations == 0
); );
if ( hasContinuations ) { for ( int i = 0; i < numberOfContinuations; i++ ) {
for ( int i = 1; i < ctx.getChildCount(); i++ ) { final HqlParser.SimplePathElementContext continuation = ctx.simplePathElement( i );
final HqlParser.SimplePathElementContext continuation = (HqlParser.SimplePathElementContext) ctx.getChild( i ); final HqlParser.IdentifierContext identifier = continuation.identifier();
final HqlParser.IdentifierContext identifier = continuation.identifier(); assert identifier.getChildCount() == 1;
assert identifier.getChildCount() == 1; dotIdentifierConsumer.consumeIdentifier(
dotIdentifierConsumer.consumeIdentifier( visitIdentifier( identifier ),
visitIdentifier( identifier ), false,
false, i+1 == numberOfContinuations
i >= numberOfContinuations );
);
}
} }
return dotIdentifierConsumer.getConsumedPart(); return dotIdentifierConsumer.getConsumedPart();
@ -5232,7 +5208,8 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
consumeManagedTypeReference( ctx.path() ); consumeManagedTypeReference( ctx.path() );
final String treatTargetName = ctx.simplePath().getText(); final String treatTargetName = ctx.simplePath().getText();
final String treatTargetEntityName = getCreationContext().getJpaMetamodel().qualifyImportableName( treatTargetName ); final String treatTargetEntityName =
getCreationContext().getJpaMetamodel().qualifyImportableName( treatTargetName );
if ( treatTargetEntityName == null ) { if ( treatTargetEntityName == null ) {
throw new SemanticException( "Could not resolve treat target type '" + treatTargetName + "'" ); throw new SemanticException( "Could not resolve treat target type '" + treatTargetName + "'" );
} }
@ -5439,14 +5416,14 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
} }
} }
private <X> SqmPath<X> consumeDomainPath(HqlParser.PathContext parserPath) { private SqmPath<?> consumeDomainPath(HqlParser.PathContext parserPath) {
final SemanticPathPart consumedPart = (SemanticPathPart) parserPath.accept( this ); final SemanticPathPart consumedPart = (SemanticPathPart) parserPath.accept( this );
if ( consumedPart instanceof SqmPath ) { if ( consumedPart instanceof SqmPath ) {
//noinspection unchecked return (SqmPath<?>) consumedPart;
return (SqmPath<X>) consumedPart; }
else {
throw new PathException( "Expecting domain-model path, but found: " + consumedPart );
} }
throw new PathException( "Expecting domain-model path, but found: " + consumedPart );
} }
@ -5455,29 +5432,31 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
if ( consumedPart instanceof SqmPath ) { if ( consumedPart instanceof SqmPath ) {
return (SqmPath<?>) consumedPart; return (SqmPath<?>) consumedPart;
} }
else {
throw new PathException( "Expecting domain-model path, but found: " + consumedPart ); throw new PathException( "Expecting domain-model path, but found: " + consumedPart );
}
} }
private SqmPath<?> consumeManagedTypeReference(HqlParser.PathContext parserPath) { private SqmPath<?> consumeManagedTypeReference(HqlParser.PathContext parserPath) {
final SqmPath<?> sqmPath = consumeDomainPath( parserPath ); final SqmPath<?> sqmPath = consumeDomainPath( parserPath );
final SqmPathSource<?> pathSource = sqmPath.getReferencedPathSource(); final SqmPathSource<?> pathSource = sqmPath.getReferencedPathSource();
if ( pathSource.getSqmPathType() instanceof ManagedDomainType<?> ) { if ( pathSource.getSqmPathType() instanceof ManagedDomainType<?> ) {
return sqmPath; return sqmPath;
} }
throw new PathException( "Expecting ManagedType valued path [" + sqmPath.getNavigablePath() + "], but found: " + pathSource.getSqmPathType() ); else {
throw new PathException( "Expecting ManagedType valued path [" + sqmPath.getNavigablePath() + "], but found: " + pathSource.getSqmPathType() );
}
} }
private SqmPath<?> consumePluralAttributeReference(HqlParser.PathContext parserPath) { private SqmPath<?> consumePluralAttributeReference(HqlParser.PathContext parserPath) {
final SqmPath<?> sqmPath = consumeDomainPath( parserPath ); final SqmPath<?> sqmPath = consumeDomainPath( parserPath );
if ( sqmPath.getReferencedPathSource() instanceof PluralPersistentAttribute ) { if ( sqmPath.getReferencedPathSource() instanceof PluralPersistentAttribute ) {
return sqmPath; return sqmPath;
} }
else {
throw new PathException( "Expecting plural attribute valued path [" + sqmPath.getNavigablePath() + "], but found: " throw new PathException( "Expecting plural attribute valued path [" + sqmPath.getNavigablePath() + "], but found: "
+ sqmPath.getReferencedPathSource().getSqmPathType() ); + sqmPath.getReferencedPathSource().getSqmPathType() );
}
} }
private void checkFQNEntityNameJpaComplianceViolationIfNeeded(String name, EntityDomainType<?> entityDescriptor) { private void checkFQNEntityNameJpaComplianceViolationIfNeeded(String name, EntityDomainType<?> entityDescriptor) {