HHH-11538 - Skip generating joins for entity references used in equality and nullness predicates
This commit is contained in:
parent
ce32b364b4
commit
17b8d2e294
|
@ -209,6 +209,8 @@ tokens
|
|||
|
||||
protected void resolve(AST node) throws SemanticException { }
|
||||
|
||||
protected void resolve(AST node, AST predicateNode) throws SemanticException { }
|
||||
|
||||
protected void resolveSelectExpression(AST dotNode) throws SemanticException { }
|
||||
|
||||
protected void processFunction(AST functionCall,boolean inSelect) throws SemanticException { }
|
||||
|
@ -335,7 +337,7 @@ assignment
|
|||
|
||||
// For now, just use expr. Revisit after ejb3 solidifies this.
|
||||
newValue
|
||||
: expr | query
|
||||
: expr [ null ] | query
|
||||
;
|
||||
|
||||
// The query / subquery rule. Pops the current 'from node' context
|
||||
|
@ -380,7 +382,7 @@ nullPrecedence
|
|||
|
||||
orderExpr
|
||||
: { isOrderExpressionResultVariableRef( _t ) }? resultVariableRef
|
||||
| expr
|
||||
| expr [ null ]
|
||||
;
|
||||
|
||||
resultVariableRef!
|
||||
|
@ -392,7 +394,7 @@ resultVariableRef!
|
|||
;
|
||||
|
||||
groupClause
|
||||
: #(GROUP { handleClauseStart( GROUP ); } (expr)+ ( #(HAVING logicalExpr) )? ) {
|
||||
: #(GROUP { handleClauseStart( GROUP ); } (expr [ null ])+ ( #(HAVING logicalExpr) )? ) {
|
||||
handleClauseEnd();
|
||||
}
|
||||
;
|
||||
|
@ -429,7 +431,7 @@ selectExpr
|
|||
| count
|
||||
| collectionFunction // elements() or indices()
|
||||
| constant
|
||||
| arithmeticExpr
|
||||
| arithmeticExpr [ null ]
|
||||
| logicalExpr
|
||||
| parameter
|
||||
| query
|
||||
|
@ -448,7 +450,7 @@ constructor
|
|||
;
|
||||
|
||||
aggregateExpr
|
||||
: expr //p:propertyRef { resolve(#p); }
|
||||
: expr [ null ] //p:propertyRef { resolve(#p); }
|
||||
| collectionFunction
|
||||
;
|
||||
|
||||
|
@ -572,36 +574,37 @@ logicalExpr
|
|||
;
|
||||
|
||||
// TODO: Add any other comparison operators here.
|
||||
// We pass through the comparisonExpr AST to the expressions so that joins can be avoided for EQ/IN/NULLNESS
|
||||
comparisonExpr
|
||||
:
|
||||
( #(EQ exprOrSubquery exprOrSubquery)
|
||||
| #(NE exprOrSubquery exprOrSubquery)
|
||||
| #(LT exprOrSubquery exprOrSubquery)
|
||||
| #(GT exprOrSubquery exprOrSubquery)
|
||||
| #(LE exprOrSubquery exprOrSubquery)
|
||||
| #(GE exprOrSubquery exprOrSubquery)
|
||||
| #(LIKE exprOrSubquery expr ( #(ESCAPE expr) )? )
|
||||
| #(NOT_LIKE exprOrSubquery expr ( #(ESCAPE expr) )? )
|
||||
| #(BETWEEN exprOrSubquery exprOrSubquery exprOrSubquery)
|
||||
| #(NOT_BETWEEN exprOrSubquery exprOrSubquery exprOrSubquery)
|
||||
| #(IN exprOrSubquery inRhs )
|
||||
| #(NOT_IN exprOrSubquery inRhs )
|
||||
| #(IS_NULL exprOrSubquery)
|
||||
| #(IS_NOT_NULL exprOrSubquery)
|
||||
// | #(IS_TRUE expr)
|
||||
// | #(IS_FALSE expr)
|
||||
| #(EXISTS ( expr | collectionFunctionOrSubselect ) )
|
||||
( #(EQ exprOrSubquery [ currentAST.root ] exprOrSubquery [ currentAST.root ])
|
||||
| #(NE exprOrSubquery [ currentAST.root ] exprOrSubquery [ currentAST.root ])
|
||||
| #(LT exprOrSubquery [ null ] exprOrSubquery [ null ])
|
||||
| #(GT exprOrSubquery [ null ] exprOrSubquery [ null ])
|
||||
| #(LE exprOrSubquery [ null ] exprOrSubquery [ null ])
|
||||
| #(GE exprOrSubquery [ null ] exprOrSubquery [ null ])
|
||||
| #(LIKE exprOrSubquery [ null ] expr [ null ] ( #(ESCAPE expr [ null ]) )? )
|
||||
| #(NOT_LIKE exprOrSubquery [ null ] expr [ null ] ( #(ESCAPE expr [ null ]) )? )
|
||||
| #(BETWEEN exprOrSubquery [ null ] exprOrSubquery [ null ] exprOrSubquery [ null ])
|
||||
| #(NOT_BETWEEN exprOrSubquery [ null ] exprOrSubquery [ null ] exprOrSubquery [ null ])
|
||||
| #(IN exprOrSubquery [ currentAST.root ] inRhs [ currentAST.root ] )
|
||||
| #(NOT_IN exprOrSubquery [ currentAST.root ] inRhs [ currentAST.root ] )
|
||||
| #(IS_NULL exprOrSubquery [ currentAST.root ])
|
||||
| #(IS_NOT_NULL exprOrSubquery [ currentAST.root ])
|
||||
// | #(IS_TRUE expr [ null ])
|
||||
// | #(IS_FALSE expr [ null ])
|
||||
| #(EXISTS ( expr [ null ] | collectionFunctionOrSubselect ) )
|
||||
) {
|
||||
prepareLogicOperator( #comparisonExpr );
|
||||
}
|
||||
;
|
||||
|
||||
inRhs
|
||||
: #(IN_LIST ( collectionFunctionOrSubselect | ( (expr)* ) ) )
|
||||
inRhs [ AST predicateNode ]
|
||||
: #(IN_LIST ( collectionFunctionOrSubselect | ( (expr [ predicateNode ])* ) ) )
|
||||
;
|
||||
|
||||
exprOrSubquery
|
||||
: expr
|
||||
exprOrSubquery [ AST predicateNode ]
|
||||
: expr [ predicateNode ]
|
||||
| query
|
||||
| #(ANY collectionFunctionOrSubselect)
|
||||
| #(ALL collectionFunctionOrSubselect)
|
||||
|
@ -613,55 +616,55 @@ collectionFunctionOrSubselect
|
|||
| query
|
||||
;
|
||||
|
||||
expr
|
||||
: ae:addrExpr [ true ] { resolve(#ae); } // Resolve the top level 'address expression'
|
||||
| #( VECTOR_EXPR (expr)* )
|
||||
expr [ AST predicateNode ]
|
||||
: ae:addrExpr [ true ] { resolve(#ae, predicateNode); } // Resolve the top level 'address expression'
|
||||
| #( VECTOR_EXPR (expr [ predicateNode ])* )
|
||||
| constant
|
||||
| arithmeticExpr
|
||||
| arithmeticExpr [ predicateNode ]
|
||||
| functionCall // Function call, not in the SELECT clause.
|
||||
| parameter
|
||||
| count // Count, not in the SELECT clause.
|
||||
;
|
||||
|
||||
arithmeticExpr
|
||||
: #(PLUS exprOrSubquery exprOrSubquery) { prepareArithmeticOperator( #arithmeticExpr ); }
|
||||
| #(MINUS exprOrSubquery exprOrSubquery) { prepareArithmeticOperator( #arithmeticExpr ); }
|
||||
| #(DIV exprOrSubquery exprOrSubquery) { prepareArithmeticOperator( #arithmeticExpr ); }
|
||||
| #(MOD exprOrSubquery exprOrSubquery) { prepareArithmeticOperator( #arithmeticExpr ); }
|
||||
| #(STAR exprOrSubquery exprOrSubquery) { prepareArithmeticOperator( #arithmeticExpr ); }
|
||||
// | #(CONCAT expr (expr)+ ) { prepareArithmeticOperator( #arithmeticExpr ); }
|
||||
| #(UNARY_MINUS expr) { prepareArithmeticOperator( #arithmeticExpr ); }
|
||||
| caseExpr
|
||||
arithmeticExpr [ AST predicateNode ]
|
||||
: #(PLUS exprOrSubquery [ null ] exprOrSubquery [ null ]) { prepareArithmeticOperator( #arithmeticExpr ); }
|
||||
| #(MINUS exprOrSubquery [ null ] exprOrSubquery [ null ]) { prepareArithmeticOperator( #arithmeticExpr ); }
|
||||
| #(DIV exprOrSubquery [ null ] exprOrSubquery [ null ]) { prepareArithmeticOperator( #arithmeticExpr ); }
|
||||
| #(MOD exprOrSubquery [ null ] exprOrSubquery [ null ]) { prepareArithmeticOperator( #arithmeticExpr ); }
|
||||
| #(STAR exprOrSubquery [ null ] exprOrSubquery [ null ]) { prepareArithmeticOperator( #arithmeticExpr ); }
|
||||
// | #(CONCAT expr [ null ] (expr [ null ])+ ) { prepareArithmeticOperator( #arithmeticExpr ); }
|
||||
| #(UNARY_MINUS expr [ null ]) { prepareArithmeticOperator( #arithmeticExpr ); }
|
||||
| caseExpr [ predicateNode ]
|
||||
;
|
||||
|
||||
caseExpr
|
||||
: simpleCaseExpression
|
||||
| searchedCaseExpression
|
||||
caseExpr [ AST predicateNode ]
|
||||
: simpleCaseExpression [ predicateNode ]
|
||||
| searchedCaseExpression [ predicateNode ]
|
||||
;
|
||||
|
||||
expressionOrSubQuery
|
||||
: expr
|
||||
expressionOrSubQuery [ AST predicateNode ]
|
||||
: expr [ predicateNode ]
|
||||
| query
|
||||
;
|
||||
|
||||
simpleCaseExpression
|
||||
: #(CASE2 {inCase=true;} expressionOrSubQuery (simpleCaseWhenClause)+ (elseClause)?) {inCase=false;}
|
||||
simpleCaseExpression [ AST predicateNode ]
|
||||
: #(CASE2 {inCase=true;} expressionOrSubQuery [ currentAST.root ] (simpleCaseWhenClause [ currentAST.root, predicateNode ])+ (elseClause [ predicateNode ])?) {inCase=false;}
|
||||
;
|
||||
|
||||
simpleCaseWhenClause
|
||||
: #(WHEN expressionOrSubQuery expressionOrSubQuery)
|
||||
simpleCaseWhenClause [ AST predicateNode, AST superPredicateNode ]
|
||||
: #(WHEN expressionOrSubQuery [ predicateNode ] expressionOrSubQuery [ superPredicateNode ])
|
||||
;
|
||||
|
||||
elseClause
|
||||
: #(ELSE expressionOrSubQuery)
|
||||
elseClause [ AST predicateNode ]
|
||||
: #(ELSE expressionOrSubQuery [ predicateNode ])
|
||||
;
|
||||
|
||||
searchedCaseExpression
|
||||
: #(CASE {inCase = true;} (searchedCaseWhenClause)+ (elseClause)?) {inCase = false;}
|
||||
searchedCaseExpression [ AST predicateNode ]
|
||||
: #(CASE {inCase = true;} (searchedCaseWhenClause [ predicateNode ])+ (elseClause [ predicateNode ])?) {inCase = false;}
|
||||
;
|
||||
|
||||
searchedCaseWhenClause
|
||||
: #(WHEN logicalExpr expressionOrSubQuery)
|
||||
searchedCaseWhenClause [ AST predicateNode ]
|
||||
: #(WHEN logicalExpr expressionOrSubQuery [ predicateNode ])
|
||||
;
|
||||
|
||||
|
||||
|
@ -675,11 +678,11 @@ collectionFunction
|
|||
;
|
||||
|
||||
functionCall
|
||||
: #(METHOD_CALL {inFunctionCall=true;} pathAsIdent ( #(EXPR_LIST (exprOrSubquery)* ) )? ) {
|
||||
: #(METHOD_CALL {inFunctionCall=true;} pathAsIdent ( #(EXPR_LIST (exprOrSubquery [ null ])* ) )? ) {
|
||||
processFunction( #functionCall, inSelect );
|
||||
inFunctionCall=false;
|
||||
}
|
||||
| #(CAST {inFunctionCall=true;} exprOrSubquery pathAsIdent) {
|
||||
| #(CAST {inFunctionCall=true;} exprOrSubquery [ null ] pathAsIdent) {
|
||||
processCastFunction( #functionCall, inSelect );
|
||||
inFunctionCall=false;
|
||||
}
|
||||
|
@ -715,7 +718,7 @@ addrExpr! [ boolean root ]
|
|||
#addrExpr = #(#d, #lhs, #rhs);
|
||||
#addrExpr = lookupProperty(#addrExpr,root,false);
|
||||
}
|
||||
| #(i:INDEX_OP lhs2:addrExprLhs rhs2:expr) {
|
||||
| #(i:INDEX_OP lhs2:addrExprLhs rhs2:expr [ null ]) {
|
||||
#addrExpr = #(#i, #lhs2, #rhs2);
|
||||
processIndex(#addrExpr);
|
||||
}
|
||||
|
@ -794,7 +797,7 @@ mapComponentReference
|
|||
;
|
||||
|
||||
mapPropertyExpression
|
||||
: e:expr {
|
||||
: e:expr [ null ] {
|
||||
validateMapPropertyExpression( #e );
|
||||
}
|
||||
;
|
||||
|
|
|
@ -1023,6 +1023,11 @@ public class HqlSqlWalker extends HqlSqlBaseWalker implements ErrorReporter, Par
|
|||
|
||||
@Override
|
||||
protected void resolve(AST node) throws SemanticException {
|
||||
resolve(node, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void resolve(AST node, AST predicateNode) throws SemanticException {
|
||||
if ( node != null ) {
|
||||
// This is called when it's time to fully resolve a path expression.
|
||||
ResolvableNode r = (ResolvableNode) node;
|
||||
|
@ -1030,7 +1035,7 @@ public class HqlSqlWalker extends HqlSqlBaseWalker implements ErrorReporter, Par
|
|||
r.resolveInFunctionCall( false, true );
|
||||
}
|
||||
else {
|
||||
r.resolve( false, true ); // Generate implicit joins, only if necessary.
|
||||
r.resolve( false, true, null, null, predicateNode ); // Generate implicit joins, only if necessary.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -45,7 +45,8 @@ public abstract class AbstractMapComponentNode extends FromReferenceNode impleme
|
|||
boolean generateJoin,
|
||||
boolean implicitJoin,
|
||||
String classAlias,
|
||||
AST parent) throws SemanticException {
|
||||
AST parent,
|
||||
AST parentPredicate) throws SemanticException {
|
||||
if ( mapFromElement == null ) {
|
||||
final FromReferenceNode mapReference = getMapReference();
|
||||
mapReference.resolve( true, true );
|
||||
|
|
|
@ -194,7 +194,7 @@ public class DotNode extends FromReferenceNode implements DisplayableNode, Selec
|
|||
dereferenceCollection( (CollectionType) propertyType, true, true, null, parent );
|
||||
}
|
||||
|
||||
public void resolve(boolean generateJoin, boolean implicitJoin, String classAlias, AST parent)
|
||||
public void resolve(boolean generateJoin, boolean implicitJoin, String classAlias, AST parent, AST parentPredicate)
|
||||
throws SemanticException {
|
||||
// If this dot has already been resolved, stop now.
|
||||
if ( isResolved() ) {
|
||||
|
@ -227,7 +227,7 @@ public class DotNode extends FromReferenceNode implements DisplayableNode, Selec
|
|||
else if ( propertyType.isEntityType() ) {
|
||||
// The property is another class..
|
||||
checkLhsIsNotCollection();
|
||||
dereferenceEntity( (EntityType) propertyType, implicitJoin, classAlias, generateJoin, parent );
|
||||
dereferenceEntity( (EntityType) propertyType, implicitJoin, classAlias, generateJoin, parent, parentPredicate );
|
||||
initText();
|
||||
}
|
||||
else if ( propertyType.isCollectionType() ) {
|
||||
|
@ -361,7 +361,8 @@ public class DotNode extends FromReferenceNode implements DisplayableNode, Selec
|
|||
boolean implicitJoin,
|
||||
String classAlias,
|
||||
boolean generateJoin,
|
||||
AST parent) throws SemanticException {
|
||||
AST parent,
|
||||
AST parentPredicate) throws SemanticException {
|
||||
checkForCorrelatedSubquery( "dereferenceEntity" );
|
||||
// three general cases we check here as to whether to render a physical SQL join:
|
||||
// 1) is our parent a DotNode as well? If so, our property reference is
|
||||
|
@ -403,6 +404,10 @@ public class DotNode extends FromReferenceNode implements DisplayableNode, Selec
|
|||
// this is the regression style determination which matches the logic of the classic translator
|
||||
joinIsNeeded = generateJoin && ( !getWalker().isInSelect() || !getWalker().isShallowQuery() );
|
||||
}
|
||||
else if ( parentPredicate != null ) {
|
||||
// Never generate a join when we compare entities directly
|
||||
joinIsNeeded = generateJoin;
|
||||
}
|
||||
else {
|
||||
joinIsNeeded = generateJoin || ( getWalker().isInSelect() || getWalker().isInFrom() );
|
||||
}
|
||||
|
|
|
@ -109,6 +109,11 @@ public abstract class FromReferenceNode extends AbstractSelectExpression
|
|||
resolve( generateJoin, implicitJoin, classAlias, null );
|
||||
}
|
||||
|
||||
public void resolve(boolean generateJoin, boolean implicitJoin, String classAlias, AST parent)
|
||||
throws SemanticException {
|
||||
resolve( generateJoin, implicitJoin, classAlias, parent, null );
|
||||
}
|
||||
|
||||
public void prepareForDot(String propertyName) throws SemanticException {
|
||||
}
|
||||
|
||||
|
|
|
@ -102,7 +102,7 @@ public class IdentNode extends FromReferenceNode implements SelectExpression {
|
|||
setText( text );
|
||||
}
|
||||
|
||||
public void resolve(boolean generateJoin, boolean implicitJoin, String classAlias, AST parent) {
|
||||
public void resolve(boolean generateJoin, boolean implicitJoin, String classAlias, AST parent, AST parentPredicate) {
|
||||
if (!isResolved()) {
|
||||
if ( getWalker().getCurrentFromClause().isFromElementAlias( getText() ) ) {
|
||||
FromElement fromElement = getWalker().getCurrentFromClause().getFromElement( getText() );
|
||||
|
|
|
@ -65,7 +65,7 @@ public class IndexNode extends FromReferenceNode {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void resolve(boolean generateJoin, boolean implicitJoin, String classAlias, AST parent)
|
||||
public void resolve(boolean generateJoin, boolean implicitJoin, String classAlias, AST parent, AST parentPredicate)
|
||||
throws SemanticException {
|
||||
if ( isResolved() ) {
|
||||
return;
|
||||
|
|
|
@ -65,11 +65,12 @@ public class MapEntryNode extends AbstractMapComponentNode implements Aggregated
|
|||
boolean generateJoin,
|
||||
boolean implicitJoin,
|
||||
String classAlias,
|
||||
AST parent) throws SemanticException {
|
||||
AST parent,
|
||||
AST parentPredicate) throws SemanticException {
|
||||
if (parent != null) {
|
||||
throw new SemanticException( expressionDescription() + " expression cannot be further de-referenced" );
|
||||
}
|
||||
super.resolve(generateJoin, implicitJoin, classAlias, parent);
|
||||
super.resolve(generateJoin, implicitJoin, classAlias, parent, parentPredicate);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -17,15 +17,19 @@ public interface ResolvableNode {
|
|||
/**
|
||||
* Does the work of resolving an identifier or a dot
|
||||
*/
|
||||
void resolve(boolean generateJoin, boolean implicitJoin, String classAlias, AST parent, AST parentPredicate) throws SemanticException;
|
||||
/**
|
||||
* Does the work of resolving an identifier or a dot, but without a parent predicate node
|
||||
*/
|
||||
void resolve(boolean generateJoin, boolean implicitJoin, String classAlias, AST parent) throws SemanticException;
|
||||
|
||||
/**
|
||||
* Does the work of resolving an identifier or a dot, but without a parent node
|
||||
* Does the work of resolving an identifier or a dot, but without a parent predicate node or parent node
|
||||
*/
|
||||
void resolve(boolean generateJoin, boolean implicitJoin, String classAlias) throws SemanticException;
|
||||
|
||||
/**
|
||||
* Does the work of resolving an identifier or a dot, but without a parent node or alias
|
||||
* Does the work of resolving an identifier or a dot, but without a parent predicate node or parent node or alias
|
||||
*/
|
||||
void resolve(boolean generateJoin, boolean implicitJoin) throws SemanticException;
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ public class SelectExpressionImpl extends FromReferenceNode implements SelectExp
|
|||
setText( text );
|
||||
}
|
||||
|
||||
public void resolve(boolean generateJoin, boolean implicitJoin, String classAlias, AST parent) throws SemanticException {
|
||||
public void resolve(boolean generateJoin, boolean implicitJoin, String classAlias, AST parent, AST parentPredicate) throws SemanticException {
|
||||
// Generated select expressions are already resolved, nothing to do.
|
||||
return;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue