HHH-17208 Implement support for @Any discriminator and key selection
This commit is contained in:
parent
bd5b9b13c4
commit
8629e012f8
|
@ -41,6 +41,7 @@ import org.hibernate.sql.results.graph.Fetch;
|
|||
import org.hibernate.sql.results.graph.FetchOptions;
|
||||
import org.hibernate.sql.results.graph.FetchParent;
|
||||
import org.hibernate.sql.results.graph.basic.BasicFetch;
|
||||
import org.hibernate.sql.results.graph.basic.BasicResult;
|
||||
import org.hibernate.type.BasicType;
|
||||
import org.hibernate.type.descriptor.java.ClassJavaType;
|
||||
import org.hibernate.type.descriptor.java.JavaType;
|
||||
|
@ -334,20 +335,19 @@ public class AnyDiscriminatorPart implements DiscriminatorMapping, FetchOptions
|
|||
return FetchTiming.IMMEDIATE;
|
||||
}
|
||||
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// NOTE : the following are "unsupported" because handling for any-mapping
|
||||
// discriminators into SQL AST is handled by outside code. Consolidate
|
||||
// with `EntityDiscriminatorMapping` to use these contracts for any-mapping
|
||||
// discriminators as well.
|
||||
|
||||
@Override
|
||||
public <T> DomainResult<T> createDomainResult(
|
||||
NavigablePath navigablePath,
|
||||
TableGroup tableGroup,
|
||||
String resultVariable,
|
||||
DomainResultCreationState creationState) {
|
||||
throw new UnsupportedOperationException();
|
||||
final SqlSelection sqlSelection = resolveSqlSelection( navigablePath, tableGroup, creationState );
|
||||
return new BasicResult<>(
|
||||
sqlSelection.getValuesArrayPosition(),
|
||||
resultVariable,
|
||||
jdbcMapping(),
|
||||
navigablePath
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -356,7 +356,11 @@ public class AnyDiscriminatorPart implements DiscriminatorMapping, FetchOptions
|
|||
JdbcMapping jdbcMappingToUse,
|
||||
TableGroup tableGroup,
|
||||
SqlAstCreationState creationState) {
|
||||
throw new UnsupportedOperationException();
|
||||
return creationState.getSqlExpressionResolver().resolveSqlExpression( tableGroup.resolveTableReference(
|
||||
navigablePath,
|
||||
this,
|
||||
getContainingTableExpression()
|
||||
), this );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -364,7 +368,7 @@ public class AnyDiscriminatorPart implements DiscriminatorMapping, FetchOptions
|
|||
NavigablePath navigablePath,
|
||||
TableGroup tableGroup,
|
||||
DomainResultCreationState creationState) {
|
||||
throw new UnsupportedOperationException();
|
||||
resolveSqlSelection( navigablePath, tableGroup, creationState );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -373,6 +377,19 @@ public class AnyDiscriminatorPart implements DiscriminatorMapping, FetchOptions
|
|||
TableGroup tableGroup,
|
||||
DomainResultCreationState creationState,
|
||||
BiConsumer<SqlSelection, JdbcMapping> selectionConsumer) {
|
||||
throw new UnsupportedOperationException();
|
||||
selectionConsumer.accept( resolveSqlSelection( navigablePath, tableGroup, creationState ), getJdbcMapping() );
|
||||
}
|
||||
|
||||
private SqlSelection resolveSqlSelection(
|
||||
NavigablePath navigablePath,
|
||||
TableGroup tableGroup,
|
||||
DomainResultCreationState creationState) {
|
||||
final SqlAstCreationState sqlAstCreationState = creationState.getSqlAstCreationState();
|
||||
return sqlAstCreationState.getSqlExpressionResolver().resolveSqlSelection(
|
||||
resolveSqlExpression( navigablePath, null, tableGroup, sqlAstCreationState ),
|
||||
jdbcMapping().getJdbcJavaType(),
|
||||
null,
|
||||
creationState.getSqlAstCreationState().getCreationContext().getSessionFactory().getTypeConfiguration()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,6 +33,7 @@ import org.hibernate.sql.results.graph.Fetch;
|
|||
import org.hibernate.sql.results.graph.FetchOptions;
|
||||
import org.hibernate.sql.results.graph.FetchParent;
|
||||
import org.hibernate.sql.results.graph.basic.BasicFetch;
|
||||
import org.hibernate.sql.results.graph.basic.BasicResult;
|
||||
import org.hibernate.type.descriptor.java.JavaType;
|
||||
|
||||
/**
|
||||
|
@ -322,8 +323,13 @@ public class AnyKeyPart implements BasicValuedModelPart, FetchOptions {
|
|||
TableGroup tableGroup,
|
||||
String resultVariable,
|
||||
DomainResultCreationState creationState) {
|
||||
// todo (6.2) : how is this correct?
|
||||
return anyPart.createDomainResult( navigablePath, tableGroup, resultVariable, creationState );
|
||||
final SqlSelection sqlSelection = resolveSqlSelection( navigablePath, tableGroup, creationState );
|
||||
return new BasicResult<>(
|
||||
sqlSelection.getValuesArrayPosition(),
|
||||
resultVariable,
|
||||
jdbcMapping,
|
||||
navigablePath
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -331,8 +337,7 @@ public class AnyKeyPart implements BasicValuedModelPart, FetchOptions {
|
|||
NavigablePath navigablePath,
|
||||
TableGroup tableGroup,
|
||||
DomainResultCreationState creationState) {
|
||||
// todo (6.2) : how is this correct?
|
||||
anyPart.applySqlSelections( navigablePath, tableGroup, creationState );
|
||||
resolveSqlSelection( navigablePath, tableGroup, creationState );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -341,7 +346,27 @@ public class AnyKeyPart implements BasicValuedModelPart, FetchOptions {
|
|||
TableGroup tableGroup,
|
||||
DomainResultCreationState creationState,
|
||||
BiConsumer<SqlSelection, JdbcMapping> selectionConsumer) {
|
||||
// todo (6.2) : how is this correct?
|
||||
anyPart.applySqlSelections( navigablePath, tableGroup, creationState, selectionConsumer );
|
||||
selectionConsumer.accept( resolveSqlSelection( navigablePath, tableGroup, creationState ), getJdbcMapping() );
|
||||
}
|
||||
|
||||
private SqlSelection resolveSqlSelection(
|
||||
NavigablePath navigablePath,
|
||||
TableGroup tableGroup,
|
||||
DomainResultCreationState creationState) {
|
||||
final TableReference tableReference = tableGroup.resolveTableReference(
|
||||
navigablePath,
|
||||
this,
|
||||
getContainingTableExpression()
|
||||
);
|
||||
final SqlExpressionResolver expressionResolver = creationState.getSqlAstCreationState().getSqlExpressionResolver();
|
||||
return expressionResolver.resolveSqlSelection(
|
||||
expressionResolver.resolveSqlExpression(
|
||||
tableReference,
|
||||
this
|
||||
),
|
||||
jdbcMapping.getJdbcJavaType(),
|
||||
null,
|
||||
creationState.getSqlAstCreationState().getCreationContext().getSessionFactory().getTypeConfiguration()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -336,7 +336,7 @@ public class EmbeddedForeignKeyDescriptor implements ForeignKeyDescriptor {
|
|||
}
|
||||
|
||||
private static TableGroup getUnderlyingTableGroup(TableGroup tableGroup) {
|
||||
if ( tableGroup instanceof VirtualTableGroup ) {
|
||||
if ( tableGroup.isVirtual() ) {
|
||||
tableGroup = getUnderlyingTableGroup( ( (VirtualTableGroup) tableGroup ).getUnderlyingTableGroup() );
|
||||
}
|
||||
return tableGroup;
|
||||
|
|
|
@ -315,7 +315,7 @@ public class SimpleForeignKeyDescriptor implements ForeignKeyDescriptor, BasicVa
|
|||
}
|
||||
|
||||
private static TableGroup getUnderlyingTableGroup(TableGroup tableGroup) {
|
||||
if ( tableGroup instanceof VirtualTableGroup ) {
|
||||
if ( tableGroup.isVirtual() ) {
|
||||
tableGroup = getUnderlyingTableGroup( ( (VirtualTableGroup) tableGroup ).getUnderlyingTableGroup() );
|
||||
}
|
||||
return tableGroup;
|
||||
|
|
|
@ -870,7 +870,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
|||
|
||||
private static void verifyManipulationImplicitJoin(TableGroup tableGroup) {
|
||||
//noinspection StatementWithEmptyBody
|
||||
if ( !tableGroup.isInitialized() || tableGroup instanceof VirtualTableGroup ) {
|
||||
if ( !tableGroup.isInitialized() || tableGroup.isVirtual() ) {
|
||||
// this is fine
|
||||
}
|
||||
else {
|
||||
|
@ -1244,6 +1244,9 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
|||
if ( !joinedGroup.isInitialized() ) {
|
||||
continue;
|
||||
}
|
||||
else if ( joinedGroup.isVirtual() ) {
|
||||
return hasJoins( joinedGroup );
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
|
|
@ -17,6 +17,8 @@ import org.hibernate.sql.ast.SqlAstWalker;
|
|||
import org.hibernate.sql.ast.tree.expression.Expression;
|
||||
import org.hibernate.sql.ast.tree.from.TableGroup;
|
||||
import org.hibernate.sql.ast.tree.from.TableReference;
|
||||
import org.hibernate.sql.results.graph.DomainResult;
|
||||
import org.hibernate.sql.results.graph.DomainResultCreationState;
|
||||
|
||||
public class AnyDiscriminatorPathInterpretation<T> extends AbstractSqmPathInterpretation<T> {
|
||||
private final Expression expression;
|
||||
|
@ -45,7 +47,7 @@ public class AnyDiscriminatorPathInterpretation<T> extends AbstractSqmPathInterp
|
|||
|
||||
return new AnyDiscriminatorPathInterpretation<>(
|
||||
sqmPath.getNavigablePath(),
|
||||
mapping,
|
||||
mapping.getDiscriminatorMapping(),
|
||||
tableGroup,
|
||||
expression
|
||||
);
|
||||
|
|
|
@ -8,6 +8,7 @@ package org.hibernate.query.sqm.sql.internal;
|
|||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.hibernate.metamodel.mapping.DiscriminatedAssociationModelPart;
|
||||
import org.hibernate.metamodel.mapping.ModelPart;
|
||||
|
@ -22,11 +23,12 @@ import org.hibernate.sql.ast.tree.expression.SqlTuple;
|
|||
import org.hibernate.sql.ast.tree.expression.SqlTupleContainer;
|
||||
import org.hibernate.sql.ast.tree.from.TableGroup;
|
||||
import org.hibernate.sql.ast.tree.from.TableReference;
|
||||
import org.hibernate.sql.ast.tree.update.Assignable;
|
||||
|
||||
/**
|
||||
* SqmPathInterpretation for discriminated association (ANY) mappings
|
||||
*/
|
||||
public class DiscriminatedAssociationPathInterpretation<T> extends AbstractSqmPathInterpretation<T> implements SqlTupleContainer {
|
||||
public class DiscriminatedAssociationPathInterpretation<T> extends AbstractSqmPathInterpretation<T> implements SqlTupleContainer, Assignable {
|
||||
|
||||
public static <T> DiscriminatedAssociationPathInterpretation<T> from(
|
||||
SqmAnyValuedSimplePath<T> sqmPath,
|
||||
|
@ -86,4 +88,21 @@ public class DiscriminatedAssociationPathInterpretation<T> extends AbstractSqmPa
|
|||
public SqlTuple getSqlTuple() {
|
||||
return sqlTuple;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ColumnReference> getColumnReferences() {
|
||||
final List<ColumnReference> results = new ArrayList<>();
|
||||
visitColumnReferences( results::add );
|
||||
return results;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitColumnReferences(Consumer<ColumnReference> columnReferenceConsumer) {
|
||||
for ( Expression expression : sqlTuple.getExpressions() ) {
|
||||
if ( !( expression instanceof ColumnReference ) ) {
|
||||
throw new IllegalArgumentException( "Expecting ColumnReference, found : " + expression );
|
||||
}
|
||||
columnReferenceConsumer.accept( (ColumnReference) expression );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1515,7 +1515,7 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
|
|||
tableGroupJoin -> {
|
||||
final TableGroup group = tableGroupJoin.getJoinedGroup();
|
||||
if ( forUpdateClause.hasAlias( group.getSourceAlias() ) ) {
|
||||
if ( tableGroupJoin.isInitialized() && tableGroupJoin.getJoinType() != SqlAstJoinType.INNER && !( group instanceof VirtualTableGroup ) ) {
|
||||
if ( tableGroupJoin.isInitialized() && tableGroupJoin.getJoinType() != SqlAstJoinType.INNER && !group.isVirtual() ) {
|
||||
if ( Boolean.FALSE.equals( followOnLocking ) ) {
|
||||
throw new IllegalQueryOperationException(
|
||||
"Locking with OUTER joins is not supported" );
|
||||
|
@ -5233,7 +5233,7 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
|
|||
}
|
||||
|
||||
private String renderFromClauseRoot(TableGroup root, String separator) {
|
||||
if ( root instanceof VirtualTableGroup ) {
|
||||
if ( root.isVirtual() ) {
|
||||
for ( TableGroupJoin tableGroupJoin : root.getTableGroupJoins() ) {
|
||||
separator = renderFromClauseRoot( tableGroupJoin.getJoinedGroup(), separator );
|
||||
}
|
||||
|
@ -5382,7 +5382,7 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
|
|||
if ( !joinedGroup.isInitialized() ) {
|
||||
continue;
|
||||
}
|
||||
if ( joinedGroup instanceof VirtualTableGroup ) {
|
||||
if ( joinedGroup.isVirtual() ) {
|
||||
if ( hasNestedTableGroupsToRender( joinedGroup.getNestedTableGroupJoins() ) ) {
|
||||
return true;
|
||||
}
|
||||
|
@ -5652,7 +5652,7 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
|
|||
protected void processTableGroupJoin(TableGroupJoin tableGroupJoin, List<TableGroupJoin> tableGroupJoinCollector) {
|
||||
final TableGroup joinedGroup = tableGroupJoin.getJoinedGroup();
|
||||
|
||||
if ( joinedGroup instanceof VirtualTableGroup ) {
|
||||
if ( joinedGroup.isVirtual() ) {
|
||||
processNestedTableGroupJoins( joinedGroup, tableGroupJoinCollector );
|
||||
if ( tableGroupJoinCollector != null ) {
|
||||
tableGroupJoinCollector.addAll( joinedGroup.getTableGroupJoins() );
|
||||
|
|
|
@ -264,7 +264,7 @@ public class FromClause implements SqlAstNode {
|
|||
private boolean hasJoins(List<TableGroupJoin> tableGroupJoins) {
|
||||
for ( TableGroupJoin tableGroupJoin : tableGroupJoins ) {
|
||||
final TableGroup joinedGroup = tableGroupJoin.getJoinedGroup();
|
||||
if ( joinedGroup instanceof VirtualTableGroup ) {
|
||||
if ( joinedGroup.isVirtual() ) {
|
||||
if ( hasJoins( joinedGroup.getTableGroupJoins() ) ) {
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -202,16 +202,23 @@ public interface TableGroup extends SqlAstNode, ColumnReferenceQualifier, SqmPat
|
|||
default boolean hasRealJoins() {
|
||||
for ( TableGroupJoin join : getTableGroupJoins() ) {
|
||||
final TableGroup joinedGroup = join.getJoinedGroup();
|
||||
if ( !( joinedGroup instanceof VirtualTableGroup ) || joinedGroup.hasRealJoins() ) {
|
||||
if ( !joinedGroup.isVirtual() || joinedGroup.hasRealJoins() ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
for ( TableGroupJoin join : getNestedTableGroupJoins() ) {
|
||||
final TableGroup joinedGroup = join.getJoinedGroup();
|
||||
if ( !( joinedGroup instanceof VirtualTableGroup ) || joinedGroup.hasRealJoins() ) {
|
||||
if ( !joinedGroup.isVirtual() || joinedGroup.hasRealJoins() ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method that indicates weather this table group is {@linkplain VirtualTableGroup virtual} or not
|
||||
*/
|
||||
default boolean isVirtual() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,4 +14,9 @@ package org.hibernate.sql.ast.tree.from;
|
|||
*/
|
||||
public interface VirtualTableGroup extends TableGroup {
|
||||
TableGroup getUnderlyingTableGroup();
|
||||
|
||||
@Override
|
||||
default boolean isVirtual() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue