Fixes for subqueries in HQL select clause
Allow subqueries to occur in the select list, and allow their aliases to occur in the order by clause.
This commit is contained in:
parent
76000201eb
commit
a1a85e2517
|
@ -525,7 +525,9 @@ public abstract class BaseSqmToSqlAstConverter
|
|||
protected void consumeFromClauseRoot(SqmRoot<?> sqmRoot) {
|
||||
log.tracef( "Resolving SqmRoot [%s] to TableGroup", sqmRoot );
|
||||
|
||||
assert ! fromClauseIndex.isResolved( sqmRoot );
|
||||
if ( fromClauseIndex.isResolved( sqmRoot ) ) {
|
||||
log.tracef( "Already resolved SqmRoot [%s] to TableGroup", sqmRoot );
|
||||
}
|
||||
|
||||
final EntityPersister entityDescriptor = resolveEntityPersister( sqmRoot.getReferencedPathSource() );
|
||||
|
||||
|
|
|
@ -103,4 +103,13 @@ public class QueryLiteral<T> implements Literal, DomainResultProducer<T> {
|
|||
executionContext.getSession()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applySqlSelections(DomainResultCreationState creationState) {
|
||||
creationState.getSqlAstCreationState().getSqlExpressionResolver().resolveSqlSelection(
|
||||
this,
|
||||
type.getBasicType().getJavaTypeDescriptor(),
|
||||
creationState.getSqlAstCreationState().getCreationContext().getDomainModel().getTypeConfiguration()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,19 +11,28 @@ import java.util.List;
|
|||
import java.util.function.Consumer;
|
||||
|
||||
import org.hibernate.metamodel.mapping.MappingModelExpressable;
|
||||
import org.hibernate.query.sqm.sql.internal.DomainResultProducer;
|
||||
import org.hibernate.sql.ast.spi.SqlAstTreeHelper;
|
||||
import org.hibernate.sql.ast.SqlAstWalker;
|
||||
import org.hibernate.sql.ast.spi.SqlExpressionResolver;
|
||||
import org.hibernate.sql.ast.spi.SqlSelection;
|
||||
import org.hibernate.sql.ast.tree.SqlAstNode;
|
||||
import org.hibernate.sql.ast.tree.cte.CteConsumer;
|
||||
import org.hibernate.sql.ast.tree.expression.Expression;
|
||||
import org.hibernate.sql.ast.tree.from.FromClause;
|
||||
import org.hibernate.sql.ast.tree.predicate.Predicate;
|
||||
import org.hibernate.sql.ast.tree.predicate.PredicateContainer;
|
||||
import org.hibernate.sql.results.graph.DomainResult;
|
||||
import org.hibernate.sql.results.graph.DomainResultCreationState;
|
||||
import org.hibernate.sql.results.graph.basic.BasicResult;
|
||||
import org.hibernate.sql.results.internal.SqlSelectionImpl;
|
||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class QuerySpec implements SqlAstNode, PredicateContainer, Expression, CteConsumer {
|
||||
public class QuerySpec implements SqlAstNode, PredicateContainer, Expression, CteConsumer, DomainResultProducer {
|
||||
private final boolean isRoot;
|
||||
|
||||
private final FromClause fromClause;
|
||||
|
@ -112,6 +121,41 @@ public class QuerySpec implements SqlAstNode, PredicateContainer, Expression, Ct
|
|||
|
||||
@Override
|
||||
public MappingModelExpressable getExpressionType() {
|
||||
return null;
|
||||
SqlSelection first = selectClause.getSqlSelections().get(0);
|
||||
return ( (SqlSelectionImpl) first ).getWrappedSqlExpression().getExpressionType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applySqlSelections(DomainResultCreationState creationState) {
|
||||
SqlSelection first = selectClause.getSqlSelections().get(0);
|
||||
TypeConfiguration typeConfiguration = creationState.getSqlAstCreationState().getCreationContext().getDomainModel().getTypeConfiguration();
|
||||
JavaTypeDescriptor descriptor = ( (SqlSelectionImpl) first ).getWrappedSqlExpression().getExpressionType()
|
||||
.getJdbcMappings( typeConfiguration ).get(0).getJavaTypeDescriptor();
|
||||
creationState.getSqlAstCreationState().getSqlExpressionResolver().resolveSqlSelection(
|
||||
this,
|
||||
descriptor,
|
||||
typeConfiguration
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DomainResult createDomainResult(String resultVariable, DomainResultCreationState creationState) {
|
||||
SqlSelection first = selectClause.getSqlSelections().get(0);
|
||||
TypeConfiguration typeConfiguration = creationState.getSqlAstCreationState().getCreationContext().getDomainModel().getTypeConfiguration();
|
||||
JavaTypeDescriptor descriptor = ( (SqlSelectionImpl) first ).getWrappedSqlExpression().getExpressionType()
|
||||
.getJdbcMappings( typeConfiguration ).get(0).getJavaTypeDescriptor();
|
||||
|
||||
final SqlExpressionResolver sqlExpressionResolver = creationState.getSqlAstCreationState().getSqlExpressionResolver();
|
||||
final SqlSelection sqlSelection = sqlExpressionResolver.resolveSqlSelection(
|
||||
this,
|
||||
descriptor,
|
||||
typeConfiguration
|
||||
);
|
||||
|
||||
return new BasicResult<>(
|
||||
sqlSelection.getValuesArrayPosition(),
|
||||
resultVariable,
|
||||
descriptor
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -52,6 +52,33 @@ public class SubqueryOperatorsTest extends SessionFactoryBasedFunctionalTest {
|
|||
} );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSubqueryInVariousClauses() {
|
||||
inTransaction(
|
||||
session -> {
|
||||
List res0 = session.createQuery(
|
||||
"select (select 1) as one, (select 'foo') as foo order by one, foo, (select 2)" )
|
||||
.list();
|
||||
assertThat( res0.size(), is( 1 ) );
|
||||
List res1 = session.createQuery(
|
||||
"select (select 1) as one, (select 'foo') as foo from SimpleEntity o order by one, foo, (select 2)" )
|
||||
.list();
|
||||
assertThat( res1.size(), is( 2 ) );
|
||||
List res2 = session.createQuery(
|
||||
"select (select x.id from SimpleEntity x where x.id = o.id) as xid from SimpleEntity o order by xid" )
|
||||
.list();
|
||||
assertThat( res2.size(), is( 2 ) );
|
||||
List res3 = session.createQuery(
|
||||
"from SimpleEntity o where o.someString = (select 'aaa') and o.id >= (select 0)" )
|
||||
.list();
|
||||
assertThat( res3.size(), is( 1 ) );
|
||||
List res4 = session.createQuery(
|
||||
"from SimpleEntity o where o.id = (select y.id from SimpleEntity y where y.id = o.id)" )
|
||||
.list();
|
||||
assertThat( res4.size(), is( 2 ) );
|
||||
} );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExists() {
|
||||
inTransaction(
|
||||
|
|
Loading…
Reference in New Issue