Skip to content
This repository was archived by the owner on Mar 19, 2021. It is now read-only.
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,11 @@ selection
// I have noticed that without this predicate, Antlr will sometimes
// interpret `select a.b from Something ...` as `from` being the
// select-expression alias
: selectExpression (asKeyword? {!doesUpcomingTokenMatchAny("from")}? IDENTIFIER)?
: selectExpression (asKeyword? {!doesUpcomingTokenMatchAny("from")}? alias)?
;

alias
: IDENTIFIER
;

selectExpression
Expand Down Expand Up @@ -201,23 +205,23 @@ fromElementSpaceRoot
;

mainEntityPersisterReference
: dotIdentifierSequence (asKeyword? {!doesUpcomingTokenMatchAny("where","join")}? IDENTIFIER)?
: dotIdentifierSequence (asKeyword? {!doesUpcomingTokenMatchAny("where","join")}? alias)?
;

crossJoin
: crossKeyword joinKeyword mainEntityPersisterReference
;

jpaCollectionJoin
: inKeyword LEFT_PAREN path RIGHT_PAREN (asKeyword? IDENTIFIER)?
: inKeyword LEFT_PAREN path RIGHT_PAREN (asKeyword? alias)?
;

qualifiedJoin
: ( innerKeyword | ((leftKeyword|rightKeyword|fullKeyword)? outerKeyword) )? joinKeyword fetchKeyword? qualifiedJoinRhs (qualifiedJoinPredicate)?
;

qualifiedJoinRhs
: path (asKeyword? IDENTIFIER)?
: path (asKeyword? alias)?
;

qualifiedJoinPredicate
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: Apache License, Version 2.0
* See the LICENSE file in the root directory or visit http://www.apache.org/licenses/LICENSE-2.0
*/
package org.hibernate.query.parser;

/**
* @author Andrea Boriero
*/
public class AliasCollisionException extends SemanticException {
public AliasCollisionException(String message) {
super( message );
}

public AliasCollisionException(String message, Throwable cause) {
super( message, cause );
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: Apache License, Version 2.0
* See the LICENSE file in the root directory or visit http://www.apache.org/licenses/LICENSE-2.0
*/
package org.hibernate.query.parser.internal;

import java.util.HashSet;
import java.util.Set;

import org.hibernate.query.parser.AliasCollisionException;

/**
* @author Andrea Boriero
*/
public class AliasRegistry {
Set<String> aliases;

public AliasRegistry() {
this.aliases = new HashSet<String>();
}

public void registerAlias(String alias) {
if ( aliases.contains( alias ) ) {
throw new AliasCollisionException( "Alias collision, alias " + alias + " is used in a different clause" );
}
aliases.add( alias );
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
public class ParsingContext {
private final ConsumerContext consumerContext;
private final ImplicitAliasGenerator aliasGenerator = new ImplicitAliasGenerator();
private final AliasRegistry aliasRegistry = new AliasRegistry();

public ParsingContext(ConsumerContext consumerContext) {
this.consumerContext = consumerContext;
Expand All @@ -28,4 +29,8 @@ public ConsumerContext getConsumerContext() {
public ImplicitAliasGenerator getImplicitAliasGenerator() {
return aliasGenerator;
}

public AliasRegistry getAliasRegistry(){
return aliasRegistry;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -243,10 +243,19 @@ public SelectClause visitSelectClause(HqlParser.SelectClauseContext ctx) {
public Selection visitSelection(HqlParser.SelectionContext ctx) {
return new Selection(
visitSelectExpression( ctx.selectExpression() ),
ctx.IDENTIFIER() == null ? null : ctx.IDENTIFIER().getText()
visitAlias( ctx.alias() )
);
}

@Override
public String visitAlias(HqlParser.AliasContext ctx) {
if(ctx == null){
return null;
}
parsingContext.getAliasRegistry().registerAlias( ctx.IDENTIFIER().getText() );
return ctx.IDENTIFIER().getText();
}

@Override
public Expression visitSelectExpression(HqlParser.SelectExpressionContext ctx) {
if ( ctx.dynamicInstantiation() != null ) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ public void enterFromElementSpaceRoot(HqlParser.FromElementSpaceRootContext ctx)
final RootEntityFromElement rootEntityFromElement = fromElementBuilder.makeRootEntityFromElement(
currentFromElementSpace,
resolveEntityReference( ctx.mainEntityPersisterReference().dotIdentifierSequence() ),
interpretAlias( ctx.mainEntityPersisterReference().IDENTIFIER() )
interpretAlias( ctx.mainEntityPersisterReference().alias() )
);
fromElementMap.put( ctx.getText(), rootEntityFromElement );
}
Expand All @@ -188,11 +188,13 @@ private EntityTypeDescriptor resolveEntityReference(HqlParser.DotIdentifierSeque
return entityTypeDescriptor;
}

private String interpretAlias(TerminalNode aliasNode) {
if ( aliasNode == null ) {
private String interpretAlias(HqlParser.AliasContext ctx) {
if ( ctx == null ) {
return parsingContext.getImplicitAliasGenerator().buildUniqueImplicitAlias();
}
final TerminalNode aliasNode = ctx.IDENTIFIER();
assert aliasNode.getSymbol().getType() == HqlParser.IDENTIFIER;
parsingContext.getAliasRegistry().registerAlias( aliasNode.getText() );
return aliasNode.getText();
}

Expand All @@ -212,7 +214,7 @@ public void enterCrossJoin(HqlParser.CrossJoinContext ctx) {
final CrossJoinedFromElement join = fromElementBuilder.makeCrossJoinedFromElement(
currentFromElementSpace,
entityTypeDescriptor,
interpretAlias( ctx.mainEntityPersisterReference().IDENTIFIER() )
interpretAlias( ctx.mainEntityPersisterReference().alias() )
);
fromElementMap.put( ctx.getText(), join );
}
Expand All @@ -226,7 +228,7 @@ public void enterJpaCollectionJoin(HqlParser.JpaCollectionJoinContext ctx) {
currentFromElementSpace,
currentFromClauseStackNode,
JoinType.INNER,
interpretAlias( ctx.IDENTIFIER() ),
interpretAlias( ctx.alias() ),
false
);

Expand Down Expand Up @@ -259,7 +261,7 @@ public void enterQualifiedJoin(HqlParser.QualifiedJoinContext ctx) {
currentFromElementSpace,
currentFromClauseStackNode,
joinType,
interpretAlias( ctx.qualifiedJoinRhs().IDENTIFIER() ),
interpretAlias( ctx.qualifiedJoinRhs().alias() ),
ctx.fetchKeyword() != null
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

import java.util.Collection;

import org.hibernate.query.parser.AliasCollisionException;
import org.hibernate.query.parser.SemanticException;
import org.hibernate.query.parser.SemanticQueryInterpreter;
import org.hibernate.query.parser.internal.hql.HqlParseTreeBuilder;
Expand Down Expand Up @@ -325,6 +326,33 @@ public void testSimpleDynamicInstantiation() throws Exception {
assertNotNull( querySpec );
}

@Test(expected = AliasCollisionException.class)
public void testAliasCollision(){
final String query = "select a.address as a from Anything as a";
final SelectStatement selectStatement = (SelectStatement) SemanticQueryInterpreter.interpret(
query,
new ConsumerContextTestingImpl()
);
}

@Test(expected = AliasCollisionException.class)
public void testAliasCollisionInSubquery() throws Exception {
final String query = "Select a from Something a where a.b in ( select a from SomethingElse a where a.basic = 5) and a.c in ( select c from SomethingElse2 c where c.basic1 = 6)";
final SelectStatement selectStatement = (SelectStatement) SemanticQueryInterpreter.interpret(
query,
new ConsumerContextTestingImpl()
);
}

@Test(expected = AliasCollisionException.class)
public void testAliasCollisionInJoin() throws Exception {
final String query = "select a from Something a left outer join a.entity a on a.basic1 > 5 and a.basic2 < 20";
final SelectStatement selectStatement = (SelectStatement) SemanticQueryInterpreter.interpret(
query,
new ConsumerContextTestingImpl()
);
}

private static class DTO {
}
}