HHH-10229 - Select value from element collection results in wrong SQL being produced

This commit is contained in:
Christian Beikov 2016-09-19 16:46:33 +02:00 committed by Steve Ebersole
parent 9aa164ed27
commit d48ac0f0f7
2 changed files with 85 additions and 15 deletions

View File

@ -39,6 +39,11 @@ public class IdentNode extends FromReferenceNode implements SelectExpression {
}
private boolean nakedPropertyRef;
private String[] columns;
public String[] getColumns() {
return columns;
}
public void resolveIndex(AST parent) throws SemanticException {
// An ident node can represent an index expression if the ident
@ -80,14 +85,58 @@ public class IdentNode extends FromReferenceNode implements SelectExpression {
getWalker().addQuerySpaces(queryableCollection.getCollectionSpaces()); // Always add the collection's query spaces.
}
protected String[] resolveColumns(QueryableCollection collectionPersister) {
final FromElement fromElement = getFromElement();
return fromElement.toColumns(
fromElement.getCollectionTableAlias(),
"elements", // the JPA VALUE "qualifier" is the same concept as the HQL ELEMENTS function/property
getWalker().isInSelect()
);
}
private void initText(String[] columns) {
String text = StringHelper.join( ", ", columns );
if ( columns.length > 1 && getWalker().isComparativeExpressionClause() ) {
text = "(" + text + ")";
}
setText( text );
}
public void resolve(boolean generateJoin, boolean implicitJoin, String classAlias, AST parent) {
if (!isResolved()) {
if ( getWalker().getCurrentFromClause().isFromElementAlias( getText() ) ) {
if (resolveAsAlias()) {
FromElement fromElement = getWalker().getCurrentFromClause().getFromElement( getText() );
if ( fromElement.getQueryableCollection() != null && fromElement.getQueryableCollection().getElementType().isComponentType() ) {
if ( getWalker().isInSelect() ) {
// This is a reference to an element collection
setFromElement( fromElement );
super.setDataType( fromElement.getQueryableCollection().getElementType() );
this.columns = resolveColumns( fromElement.getQueryableCollection() );
initText( getColumns() );
setFirstChild( null );
// Don't resolve it
}
else {
resolveAsAlias();
// Don't resolve it
}
}
else if ( resolveAsAlias() ) {
setResolved();
// We represent a from-clause alias
}
}
else if (
getColumns() != null
&& ( getWalker().getAST() instanceof AbstractMapComponentNode || getWalker().getAST() instanceof IndexNode )
&& getWalker().getCurrentFromClause().isFromElementAlias( getOriginalText() )
) {
// We might have to revert our decision that this is naked element collection reference when we encounter it is embedded in a map function
setText( getOriginalText() );
if ( resolveAsAlias() ) {
setResolved();
}
}
else if (parent != null && parent.getType() == SqlTokenTypes.DOT) {
DotNode dot = (DotNode) parent;
if (parent.getFirstChild() == this) {
@ -338,8 +387,13 @@ public class IdentNode extends FromReferenceNode implements SelectExpression {
else {
FromElement fe = getFromElement();
if (fe != null) {
if ( fe.getQueryableCollection() != null && fe.getQueryableCollection().getElementType().isComponentType() ) {
ColumnHelper.generateScalarColumns( this, getColumns(), i );
}
else {
setText(fe.renderScalarIdentifierSelect(i));
}
}
else {
ColumnHelper.generateSingleScalarColumn(this, i);
}

View File

@ -14,7 +14,6 @@ import javax.persistence.Column;
import javax.persistence.ElementCollection;
import javax.persistence.Embeddable;
import javax.persistence.Entity;
import javax.persistence.EntityManager;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.GeneratedValue;
@ -33,10 +32,12 @@ import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
import org.hibernate.testing.TestForIssue;
import org.junit.Test;
import static org.hibernate.testing.transaction.TransactionUtil.doInJPA;
/**
* @author Steve Ebersole
* @author Christian Beikov
*/
public class MapJoinTest2 extends BaseEntityManagerFunctionalTestCase {
public class MapJoinTestWithEmbeddable extends BaseEntityManagerFunctionalTestCase {
@Override
protected Class<?>[] getAnnotatedClasses() {
return new Class[] {Batch.class, Node.class, BatchNodeMetadata.class};
@ -45,9 +46,8 @@ public class MapJoinTest2 extends BaseEntityManagerFunctionalTestCase {
@Test
@TestForIssue( jiraKey = "HHH-10455" )
public void testSelectingKeyOfMapJoin() {
EntityManager em = getOrCreateEntityManager();
CriteriaBuilder cb = em.getCriteriaBuilder();
doInJPA( this::entityManagerFactory, entityManager -> {
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<Node> query = cb.createQuery( Node.class );
Root<Batch> root = query.from( Batch.class );
@ -56,9 +56,25 @@ public class MapJoinTest2 extends BaseEntityManagerFunctionalTestCase {
query.select( nodes.key() );
query.where( cb.equal( root.get( "id" ), 1 ) );
em.createQuery( query ).getResultList();
entityManager.createQuery( query ).getResultList();
} );
}
em.close();
@Test
@TestForIssue( jiraKey = "HHH-10229" )
public void testSelectingValueOfMapJoin() {
doInJPA( this::entityManagerFactory, entityManager -> {
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<Node> query = cb.createQuery( Node.class );
Root<Batch> root = query.from( Batch.class );
MapJoin nodes = (MapJoin) root.join( "batchNodeMetadata" );
query.select( nodes );
query.where( cb.equal( root.get( "id" ), 1 ) );
entityManager.createQuery( query ).getResultList();
} );
}
@Entity