HHH-3698 & HHH-3699 : HQL parameter binding issues
git-svn-id: https://svn.jboss.org/repos/hibernate/core/trunk@15758 1b8cb986-b30d-0410-93ca-fae66ebed9b2
This commit is contained in:
parent
54b9e03c22
commit
52ed395147
|
@ -68,6 +68,7 @@ import org.hibernate.hql.ast.tree.SelectExpression;
|
||||||
import org.hibernate.hql.ast.tree.UpdateStatement;
|
import org.hibernate.hql.ast.tree.UpdateStatement;
|
||||||
import org.hibernate.hql.ast.tree.Node;
|
import org.hibernate.hql.ast.tree.Node;
|
||||||
import org.hibernate.hql.ast.tree.OperatorNode;
|
import org.hibernate.hql.ast.tree.OperatorNode;
|
||||||
|
import org.hibernate.hql.ast.tree.ParameterContainer;
|
||||||
import org.hibernate.hql.ast.util.ASTPrinter;
|
import org.hibernate.hql.ast.util.ASTPrinter;
|
||||||
import org.hibernate.hql.ast.util.ASTUtil;
|
import org.hibernate.hql.ast.util.ASTUtil;
|
||||||
import org.hibernate.hql.ast.util.AliasGenerator;
|
import org.hibernate.hql.ast.util.AliasGenerator;
|
||||||
|
@ -355,7 +356,7 @@ public class HqlSqlWalker extends HqlSqlBaseWalker implements ErrorReporter, Par
|
||||||
if ( log.isDebugEnabled() ) {
|
if ( log.isDebugEnabled() ) {
|
||||||
log.debug( "handleWithFragment() : " + getASTPrinter().showAsString( hqlSqlWithNode, "-- with clause --" ) );
|
log.debug( "handleWithFragment() : " + getASTPrinter().showAsString( hqlSqlWithNode, "-- with clause --" ) );
|
||||||
}
|
}
|
||||||
WithClauseVisitor visitor = new WithClauseVisitor();
|
WithClauseVisitor visitor = new WithClauseVisitor( fromElement );
|
||||||
NodeTraverser traverser = new NodeTraverser( visitor );
|
NodeTraverser traverser = new NodeTraverser( visitor );
|
||||||
traverser.traverseDepthFirst( hqlSqlWithNode );
|
traverser.traverseDepthFirst( hqlSqlWithNode );
|
||||||
FromElement referencedFromElement = visitor.getReferencedFromElement();
|
FromElement referencedFromElement = visitor.getReferencedFromElement();
|
||||||
|
@ -379,9 +380,14 @@ public class HqlSqlWalker extends HqlSqlBaseWalker implements ErrorReporter, Par
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class WithClauseVisitor implements NodeTraverser.VisitationStrategy {
|
private static class WithClauseVisitor implements NodeTraverser.VisitationStrategy {
|
||||||
|
private final FromElement joinFragment;
|
||||||
private FromElement referencedFromElement;
|
private FromElement referencedFromElement;
|
||||||
private String joinAlias;
|
private String joinAlias;
|
||||||
|
|
||||||
|
public WithClauseVisitor(FromElement fromElement) {
|
||||||
|
this.joinFragment = fromElement;
|
||||||
|
}
|
||||||
|
|
||||||
public void visit(AST node) {
|
public void visit(AST node) {
|
||||||
// todo : currently expects that the individual with expressions apply to the same sql table join.
|
// todo : currently expects that the individual with expressions apply to the same sql table join.
|
||||||
// This may not be the case for joined-subclass where the property values
|
// This may not be the case for joined-subclass where the property values
|
||||||
|
@ -393,7 +399,6 @@ public class HqlSqlWalker extends HqlSqlBaseWalker implements ErrorReporter, Par
|
||||||
// 2) here we would need to track each comparison individually, along with
|
// 2) here we would need to track each comparison individually, along with
|
||||||
// the join alias to which it applies and then pass that information
|
// the join alias to which it applies and then pass that information
|
||||||
// back to the FromElement so it can pass it along to the JoinSequence
|
// back to the FromElement so it can pass it along to the JoinSequence
|
||||||
|
|
||||||
if ( node instanceof DotNode ) {
|
if ( node instanceof DotNode ) {
|
||||||
DotNode dotNode = ( DotNode ) node;
|
DotNode dotNode = ( DotNode ) node;
|
||||||
FromElement fromElement = dotNode.getFromElement();
|
FromElement fromElement = dotNode.getFromElement();
|
||||||
|
@ -414,6 +419,25 @@ public class HqlSqlWalker extends HqlSqlBaseWalker implements ErrorReporter, Par
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if ( node instanceof ParameterNode ) {
|
||||||
|
applyParameterSpecification( ( ( ParameterNode ) node ).getHqlParameterSpecification() );
|
||||||
|
}
|
||||||
|
else if ( node instanceof ParameterContainer ) {
|
||||||
|
applyParameterSpecifications( ( ParameterContainer ) node );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void applyParameterSpecifications(ParameterContainer parameterContainer) {
|
||||||
|
if ( parameterContainer.hasEmbeddedParameters() ) {
|
||||||
|
ParameterSpecification[] specs = parameterContainer.getEmbeddedParameters();
|
||||||
|
for ( int i = 0; i < specs.length; i++ ) {
|
||||||
|
applyParameterSpecification( specs[i] );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void applyParameterSpecification(ParameterSpecification paramSpec) {
|
||||||
|
joinFragment.addEmbeddedParameter( paramSpec );
|
||||||
}
|
}
|
||||||
|
|
||||||
private String extractAppliedAlias(DotNode dotNode) {
|
private String extractAppliedAlias(DotNode dotNode) {
|
||||||
|
|
|
@ -590,4 +590,21 @@ public class FromElement extends HqlSqlWalkerNode implements DisplayableNode, Pa
|
||||||
public ParameterSpecification[] getEmbeddedParameters() {
|
public ParameterSpecification[] getEmbeddedParameters() {
|
||||||
return ( ParameterSpecification[] ) embeddedParameters.toArray( new ParameterSpecification[ embeddedParameters.size() ] );
|
return ( ParameterSpecification[] ) embeddedParameters.toArray( new ParameterSpecification[ embeddedParameters.size() ] );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ParameterSpecification getIndexCollectionSelectorParamSpec() {
|
||||||
|
return elementType.getIndexCollectionSelectorParamSpec();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIndexCollectionSelectorParamSpec(ParameterSpecification indexCollectionSelectorParamSpec) {
|
||||||
|
if ( indexCollectionSelectorParamSpec == null ) {
|
||||||
|
if ( elementType.getIndexCollectionSelectorParamSpec() != null ) {
|
||||||
|
embeddedParameters.remove( elementType.getIndexCollectionSelectorParamSpec() );
|
||||||
|
elementType.setIndexCollectionSelectorParamSpec( null );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
elementType.setIndexCollectionSelectorParamSpec( indexCollectionSelectorParamSpec );
|
||||||
|
addEmbeddedParameter( indexCollectionSelectorParamSpec );
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,7 @@ import java.util.Map;
|
||||||
|
|
||||||
import org.hibernate.MappingException;
|
import org.hibernate.MappingException;
|
||||||
import org.hibernate.QueryException;
|
import org.hibernate.QueryException;
|
||||||
|
import org.hibernate.param.ParameterSpecification;
|
||||||
import org.hibernate.util.ArrayHelper;
|
import org.hibernate.util.ArrayHelper;
|
||||||
import org.hibernate.engine.JoinSequence;
|
import org.hibernate.engine.JoinSequence;
|
||||||
import org.hibernate.hql.CollectionProperties;
|
import org.hibernate.hql.CollectionProperties;
|
||||||
|
@ -62,6 +63,7 @@ class FromElementType {
|
||||||
private CollectionPropertyMapping collectionPropertyMapping;
|
private CollectionPropertyMapping collectionPropertyMapping;
|
||||||
private JoinSequence joinSequence;
|
private JoinSequence joinSequence;
|
||||||
private String collectionSuffix;
|
private String collectionSuffix;
|
||||||
|
private ParameterSpecification indexCollectionSelectorParamSpec;
|
||||||
|
|
||||||
public FromElementType(FromElement fromElement, EntityPersister persister, EntityType entityType) {
|
public FromElementType(FromElement fromElement, EntityPersister persister, EntityType entityType) {
|
||||||
this.fromElement = fromElement;
|
this.fromElement = fromElement;
|
||||||
|
@ -435,4 +437,12 @@ class FromElementType {
|
||||||
public boolean isEntity() {
|
public boolean isEntity() {
|
||||||
return persister != null;
|
return persister != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ParameterSpecification getIndexCollectionSelectorParamSpec() {
|
||||||
|
return indexCollectionSelectorParamSpec;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIndexCollectionSelectorParamSpec(ParameterSpecification indexCollectionSelectorParamSpec) {
|
||||||
|
this.indexCollectionSelectorParamSpec = indexCollectionSelectorParamSpec;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -116,14 +116,15 @@ public class IndexNode extends FromReferenceNode {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The 'from element' that represents the elements of the collection.
|
||||||
|
setFromElement( fromElement );
|
||||||
|
|
||||||
// Add the condition to the join sequence that qualifies the indexed element.
|
// Add the condition to the join sequence that qualifies the indexed element.
|
||||||
AST index = collectionNode.getNextSibling(); // The index should be a constant, which will have been processed already.
|
AST selector = collectionNode.getNextSibling();
|
||||||
if ( index == null ) {
|
if ( selector == null ) {
|
||||||
throw new QueryException( "No index value!" );
|
throw new QueryException( "No index value!" );
|
||||||
}
|
}
|
||||||
|
|
||||||
setFromElement( fromElement ); // The 'from element' that represents the elements of the collection.
|
|
||||||
|
|
||||||
// Sometimes use the element table alias, sometimes use the... umm... collection table alias (many to many)
|
// Sometimes use the element table alias, sometimes use the... umm... collection table alias (many to many)
|
||||||
String collectionTableAlias = elementTable;
|
String collectionTableAlias = elementTable;
|
||||||
if ( elem.getCollectionTableAlias() != null ) {
|
if ( elem.getCollectionTableAlias() != null ) {
|
||||||
|
@ -139,13 +140,13 @@ public class IndexNode extends FromReferenceNode {
|
||||||
}
|
}
|
||||||
SqlGenerator gen = new SqlGenerator( getSessionFactoryHelper().getFactory() );
|
SqlGenerator gen = new SqlGenerator( getSessionFactoryHelper().getFactory() );
|
||||||
try {
|
try {
|
||||||
gen.simpleExpr( index ); //TODO: used to be exprNoParens! was this needed?
|
gen.simpleExpr( selector ); //TODO: used to be exprNoParens! was this needed?
|
||||||
}
|
}
|
||||||
catch ( RecognitionException e ) {
|
catch ( RecognitionException e ) {
|
||||||
throw new QueryException( e.getMessage(), e );
|
throw new QueryException( e.getMessage(), e );
|
||||||
}
|
}
|
||||||
String expression = gen.getSQL();
|
String selectorExpression = gen.getSQL();
|
||||||
joinSequence.addCondition( collectionTableAlias + '.' + indexCols[0] + " = " + expression );
|
joinSequence.addCondition( collectionTableAlias + '.' + indexCols[0] + " = " + selectorExpression );
|
||||||
|
|
||||||
// Now, set the text for this node. It should be the element columns.
|
// Now, set the text for this node. It should be the element columns.
|
||||||
String[] elementColumns = queryableCollection.getElementColumnNames( elementTable );
|
String[] elementColumns = queryableCollection.getElementColumnNames( elementTable );
|
||||||
|
@ -153,5 +154,4 @@ public class IndexNode extends FromReferenceNode {
|
||||||
setResolved();
|
setResolved();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -97,6 +97,11 @@ public class SyntheticAndFactory implements HqlSqlTokenTypes {
|
||||||
fragment.setJoinFragment( joinFragment );
|
fragment.setJoinFragment( joinFragment );
|
||||||
fragment.setFromElement( fromElement );
|
fragment.setFromElement( fromElement );
|
||||||
|
|
||||||
|
if ( fromElement.getIndexCollectionSelectorParamSpec() != null ) {
|
||||||
|
fragment.addEmbeddedParameter( fromElement.getIndexCollectionSelectorParamSpec() );
|
||||||
|
fromElement.setIndexCollectionSelectorParamSpec( null );
|
||||||
|
}
|
||||||
|
|
||||||
if ( hqlSqlWalker.isFilter() ) {
|
if ( hqlSqlWalker.isFilter() ) {
|
||||||
if ( whereFragment.indexOf( '?' ) >= 0 ) {
|
if ( whereFragment.indexOf( '?' ) >= 0 ) {
|
||||||
Type collectionFilterKeyType = hqlSqlWalker.getSessionFactoryHelper()
|
Type collectionFilterKeyType = hqlSqlWalker.getSessionFactoryHelper()
|
||||||
|
|
Loading…
Reference in New Issue