Render implicit joins as nested table group joins instead of sub queries
This commit is contained in:
parent
756afb8788
commit
1456a2dd7f
|
@ -421,6 +421,7 @@ public class LoaderSelectBuilder {
|
||||||
null,
|
null,
|
||||||
SqlAstJoinType.LEFT,
|
SqlAstJoinType.LEFT,
|
||||||
true,
|
true,
|
||||||
|
false,
|
||||||
sqlAstCreationState
|
sqlAstCreationState
|
||||||
);
|
);
|
||||||
tableGroup = tableGroupJoin.getJoinedGroup();
|
tableGroup = tableGroupJoin.getJoinedGroup();
|
||||||
|
|
|
@ -171,6 +171,7 @@ public abstract class AbstractCompositeIdentifierMapping
|
||||||
String explicitSourceAlias,
|
String explicitSourceAlias,
|
||||||
SqlAstJoinType sqlAstJoinType,
|
SqlAstJoinType sqlAstJoinType,
|
||||||
boolean fetched,
|
boolean fetched,
|
||||||
|
boolean nested,
|
||||||
SqlAliasBaseGenerator aliasBaseGenerator,
|
SqlAliasBaseGenerator aliasBaseGenerator,
|
||||||
SqlExpressionResolver sqlExpressionResolver,
|
SqlExpressionResolver sqlExpressionResolver,
|
||||||
SqlAstCreationContext creationContext) {
|
SqlAstCreationContext creationContext) {
|
||||||
|
@ -187,7 +188,12 @@ public abstract class AbstractCompositeIdentifierMapping
|
||||||
);
|
);
|
||||||
|
|
||||||
final TableGroupJoin join = new TableGroupJoin( navigablePath, SqlAstJoinType.LEFT, tableGroup, null );
|
final TableGroupJoin join = new TableGroupJoin( navigablePath, SqlAstJoinType.LEFT, tableGroup, null );
|
||||||
|
if ( nested ) {
|
||||||
|
lhs.addNestedTableGroupJoin( join );
|
||||||
|
}
|
||||||
|
else {
|
||||||
lhs.addTableGroupJoin( join );
|
lhs.addTableGroupJoin( join );
|
||||||
|
}
|
||||||
|
|
||||||
return join;
|
return join;
|
||||||
}
|
}
|
||||||
|
|
|
@ -284,6 +284,7 @@ public class EmbeddedAttributeMapping
|
||||||
String explicitSourceAlias,
|
String explicitSourceAlias,
|
||||||
SqlAstJoinType sqlAstJoinType,
|
SqlAstJoinType sqlAstJoinType,
|
||||||
boolean fetched,
|
boolean fetched,
|
||||||
|
boolean nested,
|
||||||
SqlAliasBaseGenerator aliasBaseGenerator,
|
SqlAliasBaseGenerator aliasBaseGenerator,
|
||||||
SqlExpressionResolver sqlExpressionResolver,
|
SqlExpressionResolver sqlExpressionResolver,
|
||||||
SqlAstCreationContext creationContext) {
|
SqlAstCreationContext creationContext) {
|
||||||
|
@ -299,14 +300,19 @@ public class EmbeddedAttributeMapping
|
||||||
creationContext
|
creationContext
|
||||||
);
|
);
|
||||||
|
|
||||||
final TableGroupJoin tableGroupJoin = new TableGroupJoin(
|
final TableGroupJoin join = new TableGroupJoin(
|
||||||
navigablePath,
|
navigablePath,
|
||||||
sqlAstJoinType,
|
sqlAstJoinType,
|
||||||
tableGroup
|
tableGroup
|
||||||
);
|
);
|
||||||
lhs.addTableGroupJoin( tableGroupJoin );
|
if ( nested ) {
|
||||||
|
lhs.addNestedTableGroupJoin( join );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
lhs.addTableGroupJoin( join );
|
||||||
|
}
|
||||||
|
|
||||||
return tableGroupJoin;
|
return join;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -202,6 +202,7 @@ public class EmbeddedCollectionPart implements CollectionPart, EmbeddableValuedF
|
||||||
String explicitSourceAlias,
|
String explicitSourceAlias,
|
||||||
SqlAstJoinType sqlAstJoinType,
|
SqlAstJoinType sqlAstJoinType,
|
||||||
boolean fetched,
|
boolean fetched,
|
||||||
|
boolean nested,
|
||||||
SqlAliasBaseGenerator aliasBaseGenerator,
|
SqlAliasBaseGenerator aliasBaseGenerator,
|
||||||
SqlExpressionResolver sqlExpressionResolver,
|
SqlExpressionResolver sqlExpressionResolver,
|
||||||
SqlAstCreationContext creationContext) {
|
SqlAstCreationContext creationContext) {
|
||||||
|
@ -217,14 +218,19 @@ public class EmbeddedCollectionPart implements CollectionPart, EmbeddableValuedF
|
||||||
creationContext
|
creationContext
|
||||||
);
|
);
|
||||||
|
|
||||||
final TableGroupJoin tableGroupJoin = new TableGroupJoin(
|
final TableGroupJoin join = new TableGroupJoin(
|
||||||
navigablePath,
|
navigablePath,
|
||||||
sqlAstJoinType,
|
sqlAstJoinType,
|
||||||
tableGroup,
|
tableGroup,
|
||||||
null
|
null
|
||||||
);
|
);
|
||||||
lhs.addTableGroupJoin( tableGroupJoin );
|
if ( nested ) {
|
||||||
return tableGroupJoin;
|
lhs.addNestedTableGroupJoin( join );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
lhs.addTableGroupJoin( join );
|
||||||
|
}
|
||||||
|
return join;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -37,7 +37,6 @@ import org.hibernate.sql.ast.tree.expression.ColumnReference;
|
||||||
import org.hibernate.sql.ast.tree.from.TableGroup;
|
import org.hibernate.sql.ast.tree.from.TableGroup;
|
||||||
import org.hibernate.sql.ast.tree.from.TableGroupJoin;
|
import org.hibernate.sql.ast.tree.from.TableGroupJoin;
|
||||||
import org.hibernate.sql.ast.tree.from.TableReference;
|
import org.hibernate.sql.ast.tree.from.TableReference;
|
||||||
import org.hibernate.sql.ast.tree.from.TableReferenceJoin;
|
|
||||||
import org.hibernate.sql.ast.tree.predicate.ComparisonPredicate;
|
import org.hibernate.sql.ast.tree.predicate.ComparisonPredicate;
|
||||||
import org.hibernate.sql.ast.tree.predicate.Junction;
|
import org.hibernate.sql.ast.tree.predicate.Junction;
|
||||||
import org.hibernate.sql.ast.tree.predicate.Predicate;
|
import org.hibernate.sql.ast.tree.predicate.Predicate;
|
||||||
|
@ -306,6 +305,7 @@ public class EmbeddedForeignKeyDescriptor implements ForeignKeyDescriptor {
|
||||||
null,
|
null,
|
||||||
SqlAstJoinType.INNER,
|
SqlAstJoinType.INNER,
|
||||||
true,
|
true,
|
||||||
|
false,
|
||||||
creationState.getSqlAstCreationState()
|
creationState.getSqlAstCreationState()
|
||||||
);
|
);
|
||||||
return tableGroupJoin.getJoinedGroup();
|
return tableGroupJoin.getJoinedGroup();
|
||||||
|
|
|
@ -273,6 +273,7 @@ public class EntityCollectionPart
|
||||||
String explicitSourceAlias,
|
String explicitSourceAlias,
|
||||||
SqlAstJoinType sqlAstJoinType,
|
SqlAstJoinType sqlAstJoinType,
|
||||||
boolean fetched,
|
boolean fetched,
|
||||||
|
boolean nested,
|
||||||
SqlAliasBaseGenerator aliasBaseGenerator,
|
SqlAliasBaseGenerator aliasBaseGenerator,
|
||||||
SqlExpressionResolver sqlExpressionResolver,
|
SqlExpressionResolver sqlExpressionResolver,
|
||||||
SqlAstCreationContext creationContext) {
|
SqlAstCreationContext creationContext) {
|
||||||
|
@ -282,6 +283,7 @@ public class EntityCollectionPart
|
||||||
explicitSourceAlias,
|
explicitSourceAlias,
|
||||||
sqlAstJoinType,
|
sqlAstJoinType,
|
||||||
fetched,
|
fetched,
|
||||||
|
nested,
|
||||||
aliasBaseGenerator,
|
aliasBaseGenerator,
|
||||||
sqlExpressionResolver,
|
sqlExpressionResolver,
|
||||||
creationContext
|
creationContext
|
||||||
|
|
|
@ -572,6 +572,7 @@ public class PluralAttributeMappingImpl
|
||||||
null,
|
null,
|
||||||
SqlAstJoinType.LEFT,
|
SqlAstJoinType.LEFT,
|
||||||
true,
|
true,
|
||||||
|
false,
|
||||||
creationState.getSqlAstCreationState()
|
creationState.getSqlAstCreationState()
|
||||||
);
|
);
|
||||||
return tableGroupJoin.getJoinedGroup();
|
return tableGroupJoin.getJoinedGroup();
|
||||||
|
@ -624,6 +625,7 @@ public class PluralAttributeMappingImpl
|
||||||
String explicitSourceAlias,
|
String explicitSourceAlias,
|
||||||
SqlAstJoinType sqlAstJoinType,
|
SqlAstJoinType sqlAstJoinType,
|
||||||
boolean fetched,
|
boolean fetched,
|
||||||
|
boolean nested,
|
||||||
SqlAliasBaseGenerator aliasBaseGenerator,
|
SqlAliasBaseGenerator aliasBaseGenerator,
|
||||||
SqlExpressionResolver sqlExpressionResolver,
|
SqlExpressionResolver sqlExpressionResolver,
|
||||||
SqlAstCreationContext creationContext) {
|
SqlAstCreationContext creationContext) {
|
||||||
|
@ -638,7 +640,7 @@ public class PluralAttributeMappingImpl
|
||||||
sqlExpressionResolver,
|
sqlExpressionResolver,
|
||||||
creationContext
|
creationContext
|
||||||
);
|
);
|
||||||
final TableGroupJoin tableGroupJoin = new TableGroupJoin(
|
final TableGroupJoin join = new TableGroupJoin(
|
||||||
navigablePath,
|
navigablePath,
|
||||||
sqlAstJoinType,
|
sqlAstJoinType,
|
||||||
tableGroup,
|
tableGroup,
|
||||||
|
@ -651,9 +653,14 @@ public class PluralAttributeMappingImpl
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
lhs.addTableGroupJoin( tableGroupJoin );
|
if ( nested ) {
|
||||||
|
lhs.addNestedTableGroupJoin( join );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
lhs.addTableGroupJoin( join );
|
||||||
|
}
|
||||||
|
|
||||||
return tableGroupJoin;
|
return join;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -839,6 +839,7 @@ public class ToOneAttributeMapping
|
||||||
null,
|
null,
|
||||||
getDefaultSqlAstJoinType( tableGroup ),
|
getDefaultSqlAstJoinType( tableGroup ),
|
||||||
true,
|
true,
|
||||||
|
false,
|
||||||
creationState.getSqlAstCreationState()
|
creationState.getSqlAstCreationState()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -911,6 +912,7 @@ public class ToOneAttributeMapping
|
||||||
sourceAlias,
|
sourceAlias,
|
||||||
sqlAstJoinType,
|
sqlAstJoinType,
|
||||||
fetched,
|
fetched,
|
||||||
|
false,
|
||||||
creationState.getSqlAstCreationState()
|
creationState.getSqlAstCreationState()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -929,6 +931,7 @@ public class ToOneAttributeMapping
|
||||||
String explicitSourceAlias,
|
String explicitSourceAlias,
|
||||||
SqlAstJoinType sqlAstJoinType,
|
SqlAstJoinType sqlAstJoinType,
|
||||||
boolean fetched,
|
boolean fetched,
|
||||||
|
boolean nested,
|
||||||
SqlAliasBaseGenerator aliasBaseGenerator,
|
SqlAliasBaseGenerator aliasBaseGenerator,
|
||||||
SqlExpressionResolver sqlExpressionResolver,
|
SqlExpressionResolver sqlExpressionResolver,
|
||||||
SqlAstCreationContext creationContext) {
|
SqlAstCreationContext creationContext) {
|
||||||
|
@ -944,7 +947,7 @@ public class ToOneAttributeMapping
|
||||||
sqlExpressionResolver,
|
sqlExpressionResolver,
|
||||||
creationContext
|
creationContext
|
||||||
);
|
);
|
||||||
final TableGroupJoin tableGroupJoin = new TableGroupJoin(
|
final TableGroupJoin join = new TableGroupJoin(
|
||||||
navigablePath,
|
navigablePath,
|
||||||
sqlAstJoinType,
|
sqlAstJoinType,
|
||||||
lazyTableGroup,
|
lazyTableGroup,
|
||||||
|
@ -954,7 +957,7 @@ public class ToOneAttributeMapping
|
||||||
final TableReference lhsTableReference = lhs.resolveTableReference( navigablePath, identifyingColumnsTableExpression );
|
final TableReference lhsTableReference = lhs.resolveTableReference( navigablePath, identifyingColumnsTableExpression );
|
||||||
|
|
||||||
lazyTableGroup.setTableGroupInitializerCallback(
|
lazyTableGroup.setTableGroupInitializerCallback(
|
||||||
tableGroup -> tableGroupJoin.applyPredicate(
|
tableGroup -> join.applyPredicate(
|
||||||
foreignKeyDescriptor.generateJoinPredicate(
|
foreignKeyDescriptor.generateJoinPredicate(
|
||||||
sideNature == ForeignKeyDescriptor.Nature.TARGET ? lhsTableReference : tableGroup.getPrimaryTableReference(),
|
sideNature == ForeignKeyDescriptor.Nature.TARGET ? lhsTableReference : tableGroup.getPrimaryTableReference(),
|
||||||
sideNature == ForeignKeyDescriptor.Nature.TARGET ? tableGroup.getPrimaryTableReference() : lhsTableReference,
|
sideNature == ForeignKeyDescriptor.Nature.TARGET ? tableGroup.getPrimaryTableReference() : lhsTableReference,
|
||||||
|
@ -964,14 +967,19 @@ public class ToOneAttributeMapping
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
lhs.addTableGroupJoin( tableGroupJoin );
|
if ( nested ) {
|
||||||
|
lhs.addNestedTableGroupJoin( join );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
lhs.addTableGroupJoin( join );
|
||||||
|
}
|
||||||
|
|
||||||
if ( sqlAstJoinType == SqlAstJoinType.INNER && isNullable ) {
|
if ( sqlAstJoinType == SqlAstJoinType.INNER && isNullable ) {
|
||||||
// Force initialization of the underlying table group join to retain cardinality
|
// Force initialization of the underlying table group join to retain cardinality
|
||||||
lazyTableGroup.getPrimaryTableReference();
|
lazyTableGroup.getPrimaryTableReference();
|
||||||
}
|
}
|
||||||
|
|
||||||
return tableGroupJoin;
|
return join;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -991,7 +999,7 @@ public class ToOneAttributeMapping
|
||||||
canUseInnerJoin,
|
canUseInnerJoin,
|
||||||
navigablePath,
|
navigablePath,
|
||||||
fetched,
|
fetched,
|
||||||
() -> createTableGroupJoinInternal(
|
() -> createTableGroupInternal(
|
||||||
canUseInnerJoin,
|
canUseInnerJoin,
|
||||||
navigablePath,
|
navigablePath,
|
||||||
fetched,
|
fetched,
|
||||||
|
@ -1064,7 +1072,7 @@ public class ToOneAttributeMapping
|
||||||
return getDefaultSqlAstJoinType( tableGroup );
|
return getDefaultSqlAstJoinType( tableGroup );
|
||||||
}
|
}
|
||||||
|
|
||||||
public TableGroup createTableGroupJoinInternal(
|
public TableGroup createTableGroupInternal(
|
||||||
boolean canUseInnerJoins,
|
boolean canUseInnerJoins,
|
||||||
NavigablePath navigablePath,
|
NavigablePath navigablePath,
|
||||||
boolean fetched,
|
boolean fetched,
|
||||||
|
|
|
@ -77,13 +77,13 @@ public class TableGroupImpl implements TableGroup {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean canUseInnerJoins() {
|
public List<TableGroupJoin> getNestedTableGroupJoins() {
|
||||||
return false;
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean hasTableGroupJoins() {
|
public boolean canUseInnerJoins() {
|
||||||
return tableGroupJoins != null && !tableGroupJoins.isEmpty();
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -96,6 +96,11 @@ public class TableGroupImpl implements TableGroup {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addNestedTableGroupJoin(TableGroupJoin join) {
|
||||||
|
addTableGroupJoin( join );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitTableGroupJoins(Consumer<TableGroupJoin> consumer) {
|
public void visitTableGroupJoins(Consumer<TableGroupJoin> consumer) {
|
||||||
if ( tableGroupJoins != null ) {
|
if ( tableGroupJoins != null ) {
|
||||||
|
@ -103,6 +108,10 @@ public class TableGroupImpl implements TableGroup {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitNestedTableGroupJoins(Consumer<TableGroupJoin> consumer) {
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void applyAffectedTableNames(Consumer<String> nameCollector) {
|
public void applyAffectedTableNames(Consumer<String> nameCollector) {
|
||||||
|
|
||||||
|
|
|
@ -118,6 +118,7 @@ public class DynamicFetchBuilderLegacy implements DynamicFetchBuilder, NativeQue
|
||||||
tableAlias,
|
tableAlias,
|
||||||
SqlAstJoinType.INNER,
|
SqlAstJoinType.INNER,
|
||||||
true,
|
true,
|
||||||
|
false,
|
||||||
s -> sqlAliasBase,
|
s -> sqlAliasBase,
|
||||||
creationState.getSqlExpressionResolver(),
|
creationState.getSqlExpressionResolver(),
|
||||||
creationState.getCreationContext()
|
creationState.getCreationContext()
|
||||||
|
|
|
@ -89,6 +89,7 @@ public class ImplicitFetchBuilderEmbeddable implements ImplicitFetchBuilder {
|
||||||
null,
|
null,
|
||||||
SqlAstJoinType.INNER,
|
SqlAstJoinType.INNER,
|
||||||
true,
|
true,
|
||||||
|
false,
|
||||||
creationStateImpl
|
creationStateImpl
|
||||||
);
|
);
|
||||||
return tableGroupJoin.getJoinedGroup();
|
return tableGroupJoin.getJoinedGroup();
|
||||||
|
|
|
@ -70,6 +70,7 @@ public class ImplicitModelPartResultBuilderEmbeddable
|
||||||
null,
|
null,
|
||||||
SqlAstJoinType.INNER,
|
SqlAstJoinType.INNER,
|
||||||
true,
|
true,
|
||||||
|
false,
|
||||||
creationStateImpl
|
creationStateImpl
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,6 @@ import java.util.function.Consumer;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
import jakarta.persistence.TemporalType;
|
import jakarta.persistence.TemporalType;
|
||||||
import jakarta.persistence.metamodel.EmbeddableType;
|
|
||||||
|
|
||||||
import org.hibernate.HibernateException;
|
import org.hibernate.HibernateException;
|
||||||
import org.hibernate.Internal;
|
import org.hibernate.Internal;
|
||||||
|
@ -373,8 +372,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
||||||
private final Stack<FromClauseIndex> fromClauseIndexStack = new StandardStack<>();
|
private final Stack<FromClauseIndex> fromClauseIndexStack = new StandardStack<>();
|
||||||
private SqlAstProcessingState lastPoppedProcessingState;
|
private SqlAstProcessingState lastPoppedProcessingState;
|
||||||
private FromClauseIndex lastPoppedFromClauseIndex;
|
private FromClauseIndex lastPoppedFromClauseIndex;
|
||||||
private SqlAstQueryPartProcessingStateImpl joinPredicateWrapper;
|
private SqmJoin<?, ?> currentlyProcessingJoin;
|
||||||
private SqmJoin<?, ?> currentJoin;
|
|
||||||
|
|
||||||
private final Stack<Clause> currentClauseStack = new StandardStack<>();
|
private final Stack<Clause> currentClauseStack = new StandardStack<>();
|
||||||
|
|
||||||
|
@ -2114,6 +2112,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
||||||
sqmJoin.getExplicitAlias(),
|
sqmJoin.getExplicitAlias(),
|
||||||
sqmJoin.getSqmJoinType().getCorrespondingSqlJoinType(),
|
sqmJoin.getSqmJoinType().getCorrespondingSqlJoinType(),
|
||||||
sqmJoin.isFetched(),
|
sqmJoin.isFetched(),
|
||||||
|
false,
|
||||||
this
|
this
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -2128,6 +2127,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
||||||
sqmJoin.getExplicitAlias(),
|
sqmJoin.getExplicitAlias(),
|
||||||
sqmJoin.getSqmJoinType().getCorrespondingSqlJoinType(),
|
sqmJoin.getSqmJoinType().getCorrespondingSqlJoinType(),
|
||||||
sqmJoin.isFetched(),
|
sqmJoin.isFetched(),
|
||||||
|
false,
|
||||||
this
|
this
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -2147,22 +2147,10 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
||||||
throw new IllegalStateException();
|
throw new IllegalStateException();
|
||||||
}
|
}
|
||||||
|
|
||||||
final SqmJoin<?, ?> oldJoin = currentJoin;
|
final SqmJoin<?, ?> oldJoin = currentlyProcessingJoin;
|
||||||
currentJoin = sqmJoin;
|
currentlyProcessingJoin = sqmJoin;
|
||||||
final Predicate predicate = (Predicate) sqmJoin.getJoinPredicate().accept( this );
|
joinedTableGroupJoin.applyPredicate( (Predicate) sqmJoin.getJoinPredicate().accept( this ) );
|
||||||
if ( joinPredicateWrapper == null ) {
|
currentlyProcessingJoin = oldJoin;
|
||||||
joinedTableGroupJoin.applyPredicate( predicate );
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// See #prepareReusablePath for an explanation why this is necessary
|
|
||||||
popProcessingStateStack();
|
|
||||||
|
|
||||||
final QuerySpec querySpec = joinPredicateWrapper.getInflightQueryPart().getFirstQuerySpec();
|
|
||||||
querySpec.applyPredicate( predicate );
|
|
||||||
joinedTableGroupJoin.applyPredicate( new ExistsPredicate( querySpec, getBooleanType() ) );
|
|
||||||
joinPredicateWrapper = null;
|
|
||||||
}
|
|
||||||
currentJoin = oldJoin;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
consumeExplicitJoins( sqmJoin, joinedTableGroup );
|
consumeExplicitJoins( sqmJoin, joinedTableGroup );
|
||||||
|
@ -2236,29 +2224,20 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
||||||
tableGroup,
|
tableGroup,
|
||||||
null
|
null
|
||||||
);
|
);
|
||||||
lhsTableGroup.addTableGroupJoin( tableGroupJoin );
|
|
||||||
|
|
||||||
consumeExplicitJoins( sqmJoin, tableGroupJoin.getJoinedGroup() );
|
|
||||||
|
|
||||||
// add any additional join restrictions
|
// add any additional join restrictions
|
||||||
if ( sqmJoin.getJoinPredicate() != null ) {
|
if ( sqmJoin.getJoinPredicate() != null ) {
|
||||||
final SqmJoin<?, ?> oldJoin = currentJoin;
|
final SqmJoin<?, ?> oldJoin = currentlyProcessingJoin;
|
||||||
currentJoin = sqmJoin;
|
currentlyProcessingJoin = sqmJoin;
|
||||||
final Predicate predicate = (Predicate) sqmJoin.getJoinPredicate().accept( this );
|
tableGroupJoin.applyPredicate( (Predicate) sqmJoin.getJoinPredicate().accept( this ) );
|
||||||
if ( joinPredicateWrapper == null ) {
|
currentlyProcessingJoin = oldJoin;
|
||||||
tableGroupJoin.applyPredicate( predicate );
|
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
// See #prepareReusablePath for an explanation why this is necessary
|
|
||||||
popProcessingStateStack();
|
|
||||||
|
|
||||||
final QuerySpec querySpec = joinPredicateWrapper.getInflightQueryPart().getFirstQuerySpec();
|
// Note that we add the entity join after processing the predicate because implicit joins needed in there
|
||||||
querySpec.applyPredicate( predicate );
|
// can be just ordered right before the entity join without changing the semantics
|
||||||
tableGroupJoin.applyPredicate( new ExistsPredicate( querySpec, getBooleanType() ) );
|
lhsTableGroup.addTableGroupJoin( tableGroupJoin );
|
||||||
joinPredicateWrapper = null;
|
|
||||||
}
|
consumeExplicitJoins( sqmJoin, tableGroupJoin.getJoinedGroup() );
|
||||||
currentJoin = oldJoin;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private <X> X prepareReusablePath(SqmPath<?> sqmPath, Supplier<X> supplier) {
|
private <X> X prepareReusablePath(SqmPath<?> sqmPath, Supplier<X> supplier) {
|
||||||
|
@ -2271,41 +2250,15 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
||||||
}
|
}
|
||||||
final FromClauseIndex fromClauseIndex = fromClauseIndexStack.getCurrent();
|
final FromClauseIndex fromClauseIndex = fromClauseIndexStack.getCurrent();
|
||||||
final boolean useInnerJoin = currentClauseStack.getCurrent() == Clause.SELECT;
|
final boolean useInnerJoin = currentClauseStack.getCurrent() == Clause.SELECT;
|
||||||
if ( currentClauseStack.getCurrent() == Clause.FROM && currentJoin instanceof SqmAttributeJoin<?, ?>
|
|
||||||
&& joinPredicateWrapper == null && needsJoinForPath( fromClauseIndex, sqmPath ) ) {
|
|
||||||
// If we encounter a reusable path that requires a join in the ON clause of an attribute join
|
|
||||||
// we have to transform the predicate into `.. on exists (select 1 from ... where ..)`
|
|
||||||
// Note that we don't need this for e.g. entity joins because the implicit joins needed in such ON clauses
|
|
||||||
// can be just ordered right before the entity join without changing the semantics
|
|
||||||
final QuerySpec querySpec = new QuerySpec( false );
|
|
||||||
final JdbcLiteral<Integer> jdbcLiteral = new JdbcLiteral<>( 1, basicType( Integer.class ) );
|
|
||||||
querySpec.getSelectClause().addSqlSelection(
|
|
||||||
new SqlSelectionImpl( 1, 0, jdbcLiteral )
|
|
||||||
);
|
|
||||||
joinPredicateWrapper = new SqlAstQueryPartProcessingStateImpl(
|
|
||||||
querySpec,
|
|
||||||
getCurrentProcessingState(),
|
|
||||||
this,
|
|
||||||
currentClauseStack::getCurrent
|
|
||||||
);
|
|
||||||
pushProcessingState( joinPredicateWrapper );
|
|
||||||
// Note that the pop must happen where the join predicate is applied
|
|
||||||
// This is necessary as we want to retain the FromClauseIndex of this newly created sub query
|
|
||||||
// while we are still processing expressions of the predicate
|
|
||||||
currentClauseStack.push( Clause.WHERE );
|
|
||||||
prepareReusablePath( fromClauseIndex, sqmPath, useInnerJoin, implicitJoinChecker );
|
prepareReusablePath( fromClauseIndex, sqmPath, useInnerJoin, implicitJoinChecker );
|
||||||
currentClauseStack.pop();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
prepareReusablePath( fromClauseIndex, sqmPath, useInnerJoin, implicitJoinChecker );
|
|
||||||
}
|
|
||||||
return supplier.get();
|
return supplier.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
private TableGroup prepareReusablePath(
|
private TableGroup prepareReusablePath(
|
||||||
FromClauseIndex fromClauseIndex,
|
FromClauseIndex fromClauseIndex,
|
||||||
JpaPath<?> sqmPath,
|
JpaPath<?> sqmPath,
|
||||||
boolean useInnerJoin, Consumer<TableGroup> implicitJoinChecker) {
|
boolean useInnerJoin,
|
||||||
|
Consumer<TableGroup> implicitJoinChecker) {
|
||||||
final JpaPath<?> parentPath = sqmPath.getParentPath();
|
final JpaPath<?> parentPath = sqmPath.getParentPath();
|
||||||
final TableGroup tableGroup = fromClauseIndex.findTableGroup( parentPath.getNavigablePath() );
|
final TableGroup tableGroup = fromClauseIndex.findTableGroup( parentPath.getNavigablePath() );
|
||||||
if ( tableGroup == null ) {
|
if ( tableGroup == null ) {
|
||||||
|
@ -2354,105 +2307,6 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean needsJoinForPath(FromClauseIndex fromClauseIndex, SqmPath<?> sqmPath) {
|
|
||||||
final JpaPath<?> parentPath = sqmPath.getParentPath();
|
|
||||||
final TableGroup parentTableGroup = fromClauseIndex.findTableGroup( parentPath.getNavigablePath() );
|
|
||||||
// First, check if we can find the table group for the direct parent
|
|
||||||
if ( parentTableGroup != null ) {
|
|
||||||
return needsJoinForPath( fromClauseIndex, parentTableGroup, sqmPath.getReferencedPathSource().getPathName() );
|
|
||||||
}
|
|
||||||
JpaPath<?> realParentPath = parentPath;
|
|
||||||
int realParentDistance = 0;
|
|
||||||
// Next, check if we can find the table group for the parent, after traversing up embeddable paths
|
|
||||||
if ( realParentPath.getModel() instanceof EmbeddableType<?> ) {
|
|
||||||
do {
|
|
||||||
realParentPath = realParentPath.getParentPath();
|
|
||||||
realParentDistance++;
|
|
||||||
} while ( realParentPath.getModel() instanceof EmbeddableType<?> );
|
|
||||||
final TableGroup assumedToOneTableGroup = fromClauseIndex.findTableGroup( realParentPath.getNavigablePath() );
|
|
||||||
if ( assumedToOneTableGroup != null ) {
|
|
||||||
if ( assumedToOneTableGroup.getModelPart() instanceof ToOneAttributeMapping ) {
|
|
||||||
realParentPath = parentPath.getParentPath();
|
|
||||||
final StringBuilder sb = new StringBuilder();
|
|
||||||
sb.append( sqmPath.getReferencedPathSource().getPathName() );
|
|
||||||
for ( int i = realParentDistance - 1; i >= 0; i-- ) {
|
|
||||||
sb.insert( 0, realParentPath.getNavigablePath().getUnaliasedLocalName() + '.' );
|
|
||||||
realParentPath = realParentPath.getParentPath();
|
|
||||||
}
|
|
||||||
return needsJoinForPath( fromClauseIndex, assumedToOneTableGroup, sb.toString() );
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Finally, check if we can find the grandparent table group
|
|
||||||
final TableGroup grandparentTableGroup = fromClauseIndex.findTableGroup( realParentPath.getParentPath().getNavigablePath() );
|
|
||||||
if ( grandparentTableGroup == null ) {
|
|
||||||
// without a grandparent, we always need a join
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// With the grandparent available, we can determine if the model part is a to-one mapping
|
|
||||||
final ModelPart realParentModelPart = grandparentTableGroup.getModelPart().findSubPart(
|
|
||||||
realParentPath.getNavigablePath().getUnaliasedLocalName(),
|
|
||||||
null
|
|
||||||
);
|
|
||||||
// This must be a to-one otherwise we assume to always need a join
|
|
||||||
if ( !( realParentModelPart instanceof ToOneAttributeMapping ) ) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
final ToOneAttributeMapping toOneAttributeMapping = (ToOneAttributeMapping) realParentModelPart;
|
|
||||||
final String path;
|
|
||||||
if ( realParentDistance == 0 ) {
|
|
||||||
path = sqmPath.getReferencedPathSource().getPathName();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
realParentPath = parentPath.getParentPath();
|
|
||||||
final StringBuilder sb = new StringBuilder();
|
|
||||||
sb.append( sqmPath.getReferencedPathSource().getPathName() );
|
|
||||||
for ( int i = realParentDistance - 1; i >= 0; i-- ) {
|
|
||||||
sb.insert( 0, realParentPath.getNavigablePath().getUnaliasedLocalName() + '.' );
|
|
||||||
realParentPath = realParentPath.getParentPath();
|
|
||||||
}
|
|
||||||
path = sb.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
return !toOneAttributeMapping.isTargetKeyPropertyPath( path );
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean needsJoinForPath(
|
|
||||||
FromClauseIndex fromClauseIndex,
|
|
||||||
TableGroup tableGroup,
|
|
||||||
String pathName) {
|
|
||||||
TableGroup parentTableGroup = tableGroup;
|
|
||||||
ToOneAttributeMapping toOneAttributeMapping;
|
|
||||||
ModelPartContainer modelPart = tableGroup.getModelPart();
|
|
||||||
String path;
|
|
||||||
if ( modelPart instanceof ToOneAttributeMapping ) {
|
|
||||||
toOneAttributeMapping = (ToOneAttributeMapping) modelPart;
|
|
||||||
path = pathName;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if ( !( modelPart instanceof EmbeddableValuedModelPart ) ) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
StringBuilder sb = new StringBuilder();
|
|
||||||
sb.append( pathName );
|
|
||||||
do {
|
|
||||||
sb.insert( 0, modelPart.getPartName() + '.' );
|
|
||||||
parentTableGroup = fromClauseIndex.findTableGroup( parentTableGroup.getNavigablePath().getParent() );
|
|
||||||
modelPart = parentTableGroup.getModelPart();
|
|
||||||
} while ( modelPart instanceof EmbeddableValuedModelPart );
|
|
||||||
if ( !( modelPart instanceof ToOneAttributeMapping ) ) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
toOneAttributeMapping = (ToOneAttributeMapping) modelPart;
|
|
||||||
path = sb.toString();
|
|
||||||
}
|
|
||||||
final LazyTableGroup lazyTableGroup = (LazyTableGroup) parentTableGroup;
|
|
||||||
// Unless the lazy table group is not initialized and the requested sub part is not the FK
|
|
||||||
return !lazyTableGroup.isInitialized() && !toOneAttributeMapping.isTargetKeyPropertyPath( path );
|
|
||||||
}
|
|
||||||
|
|
||||||
private TableGroup createTableGroup(TableGroup parentTableGroup, SqmPath<?> joinedPath, boolean useInnerJoin) {
|
private TableGroup createTableGroup(TableGroup parentTableGroup, SqmPath<?> joinedPath, boolean useInnerJoin) {
|
||||||
final SqmPath<?> lhsPath = joinedPath.getLhs();
|
final SqmPath<?> lhsPath = joinedPath.getLhs();
|
||||||
final FromClauseIndex fromClauseIndex = getFromClauseIndex();
|
final FromClauseIndex fromClauseIndex = getFromClauseIndex();
|
||||||
|
@ -2500,6 +2354,11 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
||||||
null,
|
null,
|
||||||
defaultSqlAstJoinType,
|
defaultSqlAstJoinType,
|
||||||
false,
|
false,
|
||||||
|
// Implicit joins in the ON clause need to be added as nested table group joins
|
||||||
|
currentClauseStack.getCurrent() == Clause.FROM
|
||||||
|
// Except for entity joins, as we can order the implicit joins before the entity join
|
||||||
|
// See consumeEntityJoin for details
|
||||||
|
&& !( currentlyProcessingJoin instanceof SqmEntityJoin<?> ),
|
||||||
this
|
this
|
||||||
);
|
);
|
||||||
tableGroup = tableGroupJoin.getJoinedGroup();
|
tableGroup = tableGroupJoin.getJoinedGroup();
|
||||||
|
@ -2963,6 +2822,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
||||||
null,
|
null,
|
||||||
SqlAstJoinType.INNER,
|
SqlAstJoinType.INNER,
|
||||||
false,
|
false,
|
||||||
|
false,
|
||||||
sqlAliasBaseManager,
|
sqlAliasBaseManager,
|
||||||
getSqlExpressionResolver(),
|
getSqlExpressionResolver(),
|
||||||
creationContext
|
creationContext
|
||||||
|
@ -4340,17 +4200,13 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public QueryPart visitSubQueryExpression(SqmSubQuery<?> sqmSubQuery) {
|
public QueryPart visitSubQueryExpression(SqmSubQuery<?> sqmSubQuery) {
|
||||||
return visitQueryPart( sqmSubQuery.getQueryPart() );
|
// The only purpose for tracking the current join is to
|
||||||
//
|
// Reset the current join for sub queries because in there, we won't add nested joins
|
||||||
// final ExpressableType<?> expressableType = determineExpressableType( sqmSubQuery );
|
final SqmJoin<?, ?> oldJoin = currentlyProcessingJoin;
|
||||||
//
|
currentlyProcessingJoin = null;
|
||||||
// return new SubQuery(
|
final QueryPart queryPart = visitQueryPart( sqmSubQuery.getQueryPart() );
|
||||||
// subQuerySpec,
|
currentlyProcessingJoin = oldJoin;
|
||||||
// expressableType instanceof BasicValuedExpressableType<?>
|
return queryPart;
|
||||||
// ? ( (BasicValuedExpressableType) expressableType ).getSqlExpressableType( getTypeConfiguration() )
|
|
||||||
// : null,
|
|
||||||
// expressableType
|
|
||||||
// );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -4807,6 +4663,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
||||||
sqmPluralPath.getExplicitAlias(),
|
sqmPluralPath.getExplicitAlias(),
|
||||||
SqlAstJoinType.INNER,
|
SqlAstJoinType.INNER,
|
||||||
false,
|
false,
|
||||||
|
false,
|
||||||
sqlAliasBaseManager,
|
sqlAliasBaseManager,
|
||||||
subQueryState,
|
subQueryState,
|
||||||
creationContext
|
creationContext
|
||||||
|
@ -5215,6 +5072,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
||||||
alias,
|
alias,
|
||||||
tableGroupJoinProducer.getDefaultSqlAstJoinType( lhs ),
|
tableGroupJoinProducer.getDefaultSqlAstJoinType( lhs ),
|
||||||
true,
|
true,
|
||||||
|
false,
|
||||||
this
|
this
|
||||||
);
|
);
|
||||||
return tableGroupJoin.getJoinedGroup();
|
return tableGroupJoin.getJoinedGroup();
|
||||||
|
|
|
@ -311,6 +311,7 @@ public class EntityValuedPathInterpretation<T> extends AbstractSqmPathInterpreta
|
||||||
null,
|
null,
|
||||||
SqlAstJoinType.INNER,
|
SqlAstJoinType.INNER,
|
||||||
false,
|
false,
|
||||||
|
false,
|
||||||
sqlAstCreationState
|
sqlAstCreationState
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -3403,9 +3403,10 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void renderTableGroup(TableGroup tableGroup, Predicate predicate) {
|
protected void renderTableGroup(TableGroup tableGroup, Predicate predicate) {
|
||||||
// Without reference joins, even a real table group does not need parenthesis
|
// Without reference joins or nested join groups, even a real table group does not need parenthesis
|
||||||
final boolean realTableGroup = tableGroup.isRealTableGroup()
|
final boolean realTableGroup = tableGroup.isRealTableGroup()
|
||||||
&& CollectionHelper.isNotEmpty( tableGroup.getTableReferenceJoins() );
|
&& ( CollectionHelper.isNotEmpty( tableGroup.getTableReferenceJoins() )
|
||||||
|
|| hasTableGroupsToRender( tableGroup.getNestedTableGroupJoins() ) );
|
||||||
if ( realTableGroup ) {
|
if ( realTableGroup ) {
|
||||||
appendSql( OPEN_PARENTHESIS );
|
appendSql( OPEN_PARENTHESIS );
|
||||||
}
|
}
|
||||||
|
@ -3415,6 +3416,7 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
|
||||||
|
|
||||||
if ( realTableGroup ) {
|
if ( realTableGroup ) {
|
||||||
renderTableReferenceJoins( tableGroup );
|
renderTableReferenceJoins( tableGroup );
|
||||||
|
processNestedTableGroupJoins( tableGroup );
|
||||||
appendSql( CLOSE_PARENTHESIS );
|
appendSql( CLOSE_PARENTHESIS );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3444,6 +3446,17 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean hasTableGroupsToRender(List<TableGroupJoin> nestedTableGroupJoins) {
|
||||||
|
for ( TableGroupJoin nestedTableGroupJoin : nestedTableGroupJoins ) {
|
||||||
|
final TableGroup joinedGroup = nestedTableGroupJoin.getJoinedGroup();
|
||||||
|
if ( !( joinedGroup instanceof LazyTableGroup ) || ( (LazyTableGroup) joinedGroup ).isInitialized() ) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
@SuppressWarnings("WeakerAccess")
|
@SuppressWarnings("WeakerAccess")
|
||||||
protected boolean renderTableReference(TableReference tableReference, LockMode lockMode) {
|
protected boolean renderTableReference(TableReference tableReference, LockMode lockMode) {
|
||||||
appendSql( tableReference.getTableExpression() );
|
appendSql( tableReference.getTableExpression() );
|
||||||
|
@ -3503,6 +3516,11 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
|
||||||
source.visitTableGroupJoins( this::processTableGroupJoin );
|
source.visitTableGroupJoins( this::processTableGroupJoin );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("WeakerAccess")
|
||||||
|
protected void processNestedTableGroupJoins(TableGroup source) {
|
||||||
|
source.visitNestedTableGroupJoins( this::processTableGroupJoin );
|
||||||
|
}
|
||||||
|
|
||||||
@SuppressWarnings("WeakerAccess")
|
@SuppressWarnings("WeakerAccess")
|
||||||
protected void processTableGroupJoin(TableGroupJoin tableGroupJoin) {
|
protected void processTableGroupJoin(TableGroupJoin tableGroupJoin) {
|
||||||
final TableGroup joinedGroup = tableGroupJoin.getJoinedGroup();
|
final TableGroup joinedGroup = tableGroupJoin.getJoinedGroup();
|
||||||
|
@ -3513,6 +3531,12 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
|
||||||
else if ( !( joinedGroup instanceof LazyTableGroup ) || ( (LazyTableGroup) joinedGroup ).getUnderlyingTableGroup() != null ) {
|
else if ( !( joinedGroup instanceof LazyTableGroup ) || ( (LazyTableGroup) joinedGroup ).getUnderlyingTableGroup() != null ) {
|
||||||
appendSql( WHITESPACE );
|
appendSql( WHITESPACE );
|
||||||
SqlAstJoinType joinType = tableGroupJoin.getJoinType();
|
SqlAstJoinType joinType = tableGroupJoin.getJoinType();
|
||||||
|
// todo (6.0): no exactly sure why this is necessary and IMO this should ideally go away.
|
||||||
|
// I realized that inverse one-to-one associations with join tables are considered "non-nullable" in the boot model.
|
||||||
|
// Due to that, we use an inner join for the table group join of that association which the following "works around"
|
||||||
|
// IMO such an association should be considered nullable. It's also odd that the association
|
||||||
|
// has the FK Side KEY, although it is clearly TARGET
|
||||||
|
// See org.hibernate.orm.test.annotations.manytoone.ManyToOneJoinTest.testOneToOneJoinTable2
|
||||||
if ( !joinedGroup.isRealTableGroup() && joinType == SqlAstJoinType.INNER && !joinedGroup.getTableReferenceJoins().isEmpty() ) {
|
if ( !joinedGroup.isRealTableGroup() && joinType == SqlAstJoinType.INNER && !joinedGroup.getTableReferenceJoins().isEmpty() ) {
|
||||||
joinType = SqlAstJoinType.LEFT;
|
joinType = SqlAstJoinType.LEFT;
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,6 +59,11 @@ public class CteTableGroup implements TableGroup {
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<TableGroupJoin> getNestedTableGroupJoins() {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean canUseInnerJoins() {
|
public boolean canUseInnerJoins() {
|
||||||
return false;
|
return false;
|
||||||
|
@ -87,18 +92,22 @@ public class CteTableGroup implements TableGroup {
|
||||||
public void visitTableGroupJoins(Consumer<TableGroupJoin> consumer) {
|
public void visitTableGroupJoins(Consumer<TableGroupJoin> consumer) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitNestedTableGroupJoins(Consumer<TableGroupJoin> consumer) {
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getGroupAlias() {
|
public String getGroupAlias() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean hasTableGroupJoins() {
|
public void addTableGroupJoin(TableGroupJoin join) {
|
||||||
return false;
|
throw new UnsupportedOperationException( );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addTableGroupJoin(TableGroupJoin join) {
|
public void addNestedTableGroupJoin(TableGroupJoin join) {
|
||||||
throw new UnsupportedOperationException( );
|
throw new UnsupportedOperationException( );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,6 +27,7 @@ public abstract class AbstractTableGroup extends AbstractColumnReferenceQualifie
|
||||||
private final SqlAliasBase sqlAliasBase;
|
private final SqlAliasBase sqlAliasBase;
|
||||||
|
|
||||||
private List<TableGroupJoin> tableGroupJoins;
|
private List<TableGroupJoin> tableGroupJoins;
|
||||||
|
private List<TableGroupJoin> nestedTableGroupJoins;
|
||||||
|
|
||||||
private final SessionFactoryImplementor sessionFactory;
|
private final SessionFactoryImplementor sessionFactory;
|
||||||
|
|
||||||
|
@ -87,13 +88,18 @@ public abstract class AbstractTableGroup extends AbstractColumnReferenceQualifie
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean canUseInnerJoins() {
|
public List<TableGroupJoin> getNestedTableGroupJoins() {
|
||||||
return canUseInnerJoins;
|
return nestedTableGroupJoins == null ? Collections.emptyList() : Collections.unmodifiableList( nestedTableGroupJoins );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean hasTableGroupJoins() {
|
public boolean isRealTableGroup() {
|
||||||
return tableGroupJoins != null && !tableGroupJoins.isEmpty();
|
return nestedTableGroupJoins != null && !nestedTableGroupJoins.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canUseInnerJoins() {
|
||||||
|
return canUseInnerJoins;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -106,6 +112,16 @@ public abstract class AbstractTableGroup extends AbstractColumnReferenceQualifie
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addNestedTableGroupJoin(TableGroupJoin join) {
|
||||||
|
if ( nestedTableGroupJoins == null ) {
|
||||||
|
nestedTableGroupJoins = new ArrayList<>();
|
||||||
|
}
|
||||||
|
if ( !nestedTableGroupJoins.contains( join ) ) {
|
||||||
|
nestedTableGroupJoins.add( join );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitTableGroupJoins(Consumer<TableGroupJoin> consumer) {
|
public void visitTableGroupJoins(Consumer<TableGroupJoin> consumer) {
|
||||||
if ( tableGroupJoins != null ) {
|
if ( tableGroupJoins != null ) {
|
||||||
|
@ -113,6 +129,13 @@ public abstract class AbstractTableGroup extends AbstractColumnReferenceQualifie
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitNestedTableGroupJoins(Consumer<TableGroupJoin> consumer) {
|
||||||
|
if ( nestedTableGroupJoins != null ) {
|
||||||
|
nestedTableGroupJoins.forEach( consumer );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return getClass().getSimpleName() + '(' + getNavigablePath() + ')';
|
return getClass().getSimpleName() + '(' + getNavigablePath() + ')';
|
||||||
|
|
|
@ -25,6 +25,7 @@ public class CompositeTableGroup implements VirtualTableGroup {
|
||||||
private final boolean fetched;
|
private final boolean fetched;
|
||||||
|
|
||||||
private List<TableGroupJoin> tableGroupJoins;
|
private List<TableGroupJoin> tableGroupJoins;
|
||||||
|
private List<TableGroupJoin> nestedTableGroupJoins;
|
||||||
|
|
||||||
public CompositeTableGroup(
|
public CompositeTableGroup(
|
||||||
NavigablePath navigablePath,
|
NavigablePath navigablePath,
|
||||||
|
@ -74,13 +75,18 @@ public class CompositeTableGroup implements VirtualTableGroup {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean canUseInnerJoins() {
|
public List<TableGroupJoin> getNestedTableGroupJoins() {
|
||||||
return underlyingTableGroup.canUseInnerJoins();
|
return nestedTableGroupJoins == null ? Collections.emptyList() : Collections.unmodifiableList( nestedTableGroupJoins );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean hasTableGroupJoins() {
|
public boolean isRealTableGroup() {
|
||||||
return tableGroupJoins != null && !tableGroupJoins.isEmpty();
|
return nestedTableGroupJoins != null && !nestedTableGroupJoins.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canUseInnerJoins() {
|
||||||
|
return underlyingTableGroup.canUseInnerJoins();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -93,6 +99,16 @@ public class CompositeTableGroup implements VirtualTableGroup {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addNestedTableGroupJoin(TableGroupJoin join) {
|
||||||
|
if ( nestedTableGroupJoins == null ) {
|
||||||
|
nestedTableGroupJoins = new ArrayList<>();
|
||||||
|
}
|
||||||
|
if ( !nestedTableGroupJoins.contains( join ) ) {
|
||||||
|
nestedTableGroupJoins.add( join );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitTableGroupJoins(Consumer<TableGroupJoin> consumer) {
|
public void visitTableGroupJoins(Consumer<TableGroupJoin> consumer) {
|
||||||
if ( tableGroupJoins != null ) {
|
if ( tableGroupJoins != null ) {
|
||||||
|
@ -100,6 +116,13 @@ public class CompositeTableGroup implements VirtualTableGroup {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitNestedTableGroupJoins(Consumer<TableGroupJoin> consumer) {
|
||||||
|
if ( nestedTableGroupJoins != null ) {
|
||||||
|
nestedTableGroupJoins.forEach( consumer );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void applyAffectedTableNames(Consumer<String> nameCollector) {
|
public void applyAffectedTableNames(Consumer<String> nameCollector) {
|
||||||
underlyingTableGroup.applyAffectedTableNames( nameCollector );
|
underlyingTableGroup.applyAffectedTableNames( nameCollector );
|
||||||
|
@ -136,6 +159,14 @@ public class CompositeTableGroup implements VirtualTableGroup {
|
||||||
if ( tableReference != null ) {
|
if ( tableReference != null ) {
|
||||||
return tableReference;
|
return tableReference;
|
||||||
}
|
}
|
||||||
|
for ( TableGroupJoin tableGroupJoin : getNestedTableGroupJoins() ) {
|
||||||
|
final TableReference primaryTableReference = tableGroupJoin.getJoinedGroup()
|
||||||
|
.getPrimaryTableReference()
|
||||||
|
.getTableReference( navigablePath, tableExpression, allowFkOptimization );
|
||||||
|
if ( primaryTableReference != null ) {
|
||||||
|
return primaryTableReference;
|
||||||
|
}
|
||||||
|
}
|
||||||
for ( TableGroupJoin tableGroupJoin : getTableGroupJoins() ) {
|
for ( TableGroupJoin tableGroupJoin : getTableGroupJoins() ) {
|
||||||
final TableReference primaryTableReference = tableGroupJoin.getJoinedGroup()
|
final TableReference primaryTableReference = tableGroupJoin.getJoinedGroup()
|
||||||
.getPrimaryTableReference()
|
.getPrimaryTableReference()
|
||||||
|
|
|
@ -71,6 +71,14 @@ public class CorrelatedTableGroup extends AbstractTableGroup {
|
||||||
if ( primaryTableReference != null ) {
|
if ( primaryTableReference != null ) {
|
||||||
return primaryTableReference;
|
return primaryTableReference;
|
||||||
}
|
}
|
||||||
|
for ( TableGroupJoin tableGroupJoin : getNestedTableGroupJoins() ) {
|
||||||
|
final TableReference groupTableReference = tableGroupJoin.getJoinedGroup()
|
||||||
|
.getPrimaryTableReference()
|
||||||
|
.getTableReference( navigablePath, tableExpression, allowFkOptimization );
|
||||||
|
if ( groupTableReference != null ) {
|
||||||
|
return groupTableReference;
|
||||||
|
}
|
||||||
|
}
|
||||||
for ( TableGroupJoin tableGroupJoin : getTableGroupJoins() ) {
|
for ( TableGroupJoin tableGroupJoin : getTableGroupJoins() ) {
|
||||||
final TableReference groupTableReference = tableGroupJoin.getJoinedGroup()
|
final TableReference groupTableReference = tableGroupJoin.getJoinedGroup()
|
||||||
.getPrimaryTableReference()
|
.getPrimaryTableReference()
|
||||||
|
|
|
@ -106,8 +106,8 @@ public class LazyTableGroup extends AbstractColumnReferenceQualifier implements
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean hasTableGroupJoins() {
|
public List<TableGroupJoin> getNestedTableGroupJoins() {
|
||||||
return tableGroup != null && tableGroup.hasTableGroupJoins();
|
return tableGroup == null ? Collections.emptyList() : tableGroup.getNestedTableGroupJoins();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -115,6 +115,11 @@ public class LazyTableGroup extends AbstractColumnReferenceQualifier implements
|
||||||
getTableGroup().addTableGroupJoin( join );
|
getTableGroup().addTableGroupJoin( join );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addNestedTableGroupJoin(TableGroupJoin join) {
|
||||||
|
getTableGroup().addNestedTableGroupJoin( join );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitTableGroupJoins(Consumer<TableGroupJoin> consumer) {
|
public void visitTableGroupJoins(Consumer<TableGroupJoin> consumer) {
|
||||||
if ( tableGroup != null ) {
|
if ( tableGroup != null ) {
|
||||||
|
@ -122,6 +127,13 @@ public class LazyTableGroup extends AbstractColumnReferenceQualifier implements
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitNestedTableGroupJoins(Consumer<TableGroupJoin> consumer) {
|
||||||
|
if ( tableGroup != null ) {
|
||||||
|
tableGroup.visitNestedTableGroupJoins( consumer );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean canUseInnerJoins() {
|
public boolean canUseInnerJoins() {
|
||||||
return canUseInnerJoins;
|
return canUseInnerJoins;
|
||||||
|
@ -159,7 +171,7 @@ public class LazyTableGroup extends AbstractColumnReferenceQualifier implements
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isRealTableGroup() {
|
public boolean isRealTableGroup() {
|
||||||
return false;
|
return tableGroup != null && tableGroup.isRealTableGroup();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -93,12 +93,12 @@ public class MutatingTableReferenceGroupWrapper implements VirtualTableGroup {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean canUseInnerJoins() {
|
public List<TableGroupJoin> getNestedTableGroupJoins() {
|
||||||
return false;
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean hasTableGroupJoins() {
|
public boolean canUseInnerJoins() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -107,10 +107,19 @@ public class MutatingTableReferenceGroupWrapper implements VirtualTableGroup {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addNestedTableGroupJoin(TableGroupJoin join) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitTableGroupJoins(Consumer<TableGroupJoin> consumer) {
|
public void visitTableGroupJoins(Consumer<TableGroupJoin> consumer) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitNestedTableGroupJoins(Consumer<TableGroupJoin> consumer) {
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<TableReferenceJoin> getTableReferenceJoins() {
|
public List<TableReferenceJoin> getTableReferenceJoins() {
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
|
|
|
@ -115,7 +115,7 @@ public class StandardTableGroup extends AbstractTableGroup {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isRealTableGroup() {
|
public boolean isRealTableGroup() {
|
||||||
return realTableGroup;
|
return realTableGroup || super.isRealTableGroup();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -159,6 +159,12 @@ public class StandardTableGroup extends AbstractTableGroup {
|
||||||
return potentiallyCreateTableReference( tableExpression );
|
return potentiallyCreateTableReference( tableExpression );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for ( TableGroupJoin tableGroupJoin : getNestedTableGroupJoins() ) {
|
||||||
|
final TableReference primaryTableReference = tableGroupJoin.getJoinedGroup().getPrimaryTableReference();
|
||||||
|
if ( primaryTableReference.getTableReference( navigablePath, tableExpression, allowFkOptimization ) != null ) {
|
||||||
|
return primaryTableReference;
|
||||||
|
}
|
||||||
|
}
|
||||||
for ( TableGroupJoin tableGroupJoin : getTableGroupJoins() ) {
|
for ( TableGroupJoin tableGroupJoin : getTableGroupJoins() ) {
|
||||||
final TableReference primaryTableReference = tableGroupJoin.getJoinedGroup().getPrimaryTableReference();
|
final TableReference primaryTableReference = tableGroupJoin.getJoinedGroup().getPrimaryTableReference();
|
||||||
if ( primaryTableReference.getTableReference( navigablePath, tableExpression, allowFkOptimization ) != null ) {
|
if ( primaryTableReference.getTableReference( navigablePath, tableExpression, allowFkOptimization ) != null ) {
|
||||||
|
|
|
@ -42,14 +42,18 @@ public interface TableGroup extends SqlAstNode, ColumnReferenceQualifier, SqmPat
|
||||||
|
|
||||||
List<TableGroupJoin> getTableGroupJoins();
|
List<TableGroupJoin> getTableGroupJoins();
|
||||||
|
|
||||||
boolean canUseInnerJoins();
|
List<TableGroupJoin> getNestedTableGroupJoins();
|
||||||
|
|
||||||
boolean hasTableGroupJoins();
|
boolean canUseInnerJoins();
|
||||||
|
|
||||||
void addTableGroupJoin(TableGroupJoin join);
|
void addTableGroupJoin(TableGroupJoin join);
|
||||||
|
|
||||||
|
void addNestedTableGroupJoin(TableGroupJoin join);
|
||||||
|
|
||||||
void visitTableGroupJoins(Consumer<TableGroupJoin> consumer);
|
void visitTableGroupJoins(Consumer<TableGroupJoin> consumer);
|
||||||
|
|
||||||
|
void visitNestedTableGroupJoins(Consumer<TableGroupJoin> consumer);
|
||||||
|
|
||||||
void applyAffectedTableNames(Consumer<String> nameCollector);
|
void applyAffectedTableNames(Consumer<String> nameCollector);
|
||||||
|
|
||||||
TableReference getPrimaryTableReference();
|
TableReference getPrimaryTableReference();
|
||||||
|
|
|
@ -8,7 +8,6 @@ package org.hibernate.sql.ast.tree.from;
|
||||||
|
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
import org.hibernate.LockMode;
|
|
||||||
import org.hibernate.query.NavigablePath;
|
import org.hibernate.query.NavigablePath;
|
||||||
import org.hibernate.sql.ast.SqlAstJoinType;
|
import org.hibernate.sql.ast.SqlAstJoinType;
|
||||||
import org.hibernate.sql.ast.spi.SqlAliasBaseGenerator;
|
import org.hibernate.sql.ast.spi.SqlAliasBaseGenerator;
|
||||||
|
@ -33,6 +32,7 @@ public interface TableGroupJoinProducer extends TableGroupProducer {
|
||||||
String explicitSourceAlias,
|
String explicitSourceAlias,
|
||||||
SqlAstJoinType sqlAstJoinType,
|
SqlAstJoinType sqlAstJoinType,
|
||||||
boolean fetched,
|
boolean fetched,
|
||||||
|
boolean nested,
|
||||||
SqlAstCreationState creationState) {
|
SqlAstCreationState creationState) {
|
||||||
return createTableGroupJoin(
|
return createTableGroupJoin(
|
||||||
navigablePath,
|
navigablePath,
|
||||||
|
@ -40,6 +40,7 @@ public interface TableGroupJoinProducer extends TableGroupProducer {
|
||||||
explicitSourceAlias,
|
explicitSourceAlias,
|
||||||
sqlAstJoinType,
|
sqlAstJoinType,
|
||||||
fetched,
|
fetched,
|
||||||
|
nested,
|
||||||
creationState.getSqlAliasBaseGenerator(),
|
creationState.getSqlAliasBaseGenerator(),
|
||||||
creationState.getSqlExpressionResolver(),
|
creationState.getSqlExpressionResolver(),
|
||||||
creationState.getCreationContext()
|
creationState.getCreationContext()
|
||||||
|
@ -55,6 +56,7 @@ public interface TableGroupJoinProducer extends TableGroupProducer {
|
||||||
String explicitSourceAlias,
|
String explicitSourceAlias,
|
||||||
SqlAstJoinType sqlAstJoinType,
|
SqlAstJoinType sqlAstJoinType,
|
||||||
boolean fetched,
|
boolean fetched,
|
||||||
|
boolean nested,
|
||||||
SqlAliasBaseGenerator aliasBaseGenerator,
|
SqlAliasBaseGenerator aliasBaseGenerator,
|
||||||
SqlExpressionResolver sqlExpressionResolver,
|
SqlExpressionResolver sqlExpressionResolver,
|
||||||
SqlAstCreationContext creationContext);
|
SqlAstCreationContext creationContext);
|
||||||
|
|
|
@ -23,6 +23,7 @@ public class UnionTableGroup implements VirtualTableGroup {
|
||||||
private final boolean canUseInnerJoins;
|
private final boolean canUseInnerJoins;
|
||||||
private final NavigablePath navigablePath;
|
private final NavigablePath navigablePath;
|
||||||
private List<TableGroupJoin> tableGroupJoins;
|
private List<TableGroupJoin> tableGroupJoins;
|
||||||
|
private List<TableGroupJoin> nestedTableGroupJoins;
|
||||||
|
|
||||||
private final UnionSubclassEntityPersister modelPart;
|
private final UnionSubclassEntityPersister modelPart;
|
||||||
private final String sourceAlias;
|
private final String sourceAlias;
|
||||||
|
@ -72,8 +73,13 @@ public class UnionTableGroup implements VirtualTableGroup {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean hasTableGroupJoins() {
|
public List<TableGroupJoin> getNestedTableGroupJoins() {
|
||||||
return tableGroupJoins != null && !tableGroupJoins.isEmpty();
|
return nestedTableGroupJoins == null ? Collections.emptyList() : Collections.unmodifiableList( nestedTableGroupJoins );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isRealTableGroup() {
|
||||||
|
return nestedTableGroupJoins != null && !nestedTableGroupJoins.isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -91,6 +97,16 @@ public class UnionTableGroup implements VirtualTableGroup {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addNestedTableGroupJoin(TableGroupJoin join) {
|
||||||
|
if ( nestedTableGroupJoins == null ) {
|
||||||
|
nestedTableGroupJoins = new ArrayList<>();
|
||||||
|
}
|
||||||
|
if ( !nestedTableGroupJoins.contains( join ) ) {
|
||||||
|
nestedTableGroupJoins.add( join );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitTableGroupJoins(Consumer<TableGroupJoin> consumer) {
|
public void visitTableGroupJoins(Consumer<TableGroupJoin> consumer) {
|
||||||
if ( tableGroupJoins != null ) {
|
if ( tableGroupJoins != null ) {
|
||||||
|
@ -98,6 +114,13 @@ public class UnionTableGroup implements VirtualTableGroup {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitNestedTableGroupJoins(Consumer<TableGroupJoin> consumer) {
|
||||||
|
if ( nestedTableGroupJoins != null ) {
|
||||||
|
nestedTableGroupJoins.forEach( consumer );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void applyAffectedTableNames(Consumer<String> nameCollector) {
|
public void applyAffectedTableNames(Consumer<String> nameCollector) {
|
||||||
}
|
}
|
||||||
|
@ -128,6 +151,15 @@ public class UnionTableGroup implements VirtualTableGroup {
|
||||||
if ( tableReference.getTableReference( navigablePath, tableExpression, allowFkOptimization ) != null ) {
|
if ( tableReference.getTableReference( navigablePath, tableExpression, allowFkOptimization ) != null ) {
|
||||||
return tableReference;
|
return tableReference;
|
||||||
}
|
}
|
||||||
|
if ( nestedTableGroupJoins != null ) {
|
||||||
|
for ( TableGroupJoin tableGroupJoin : nestedTableGroupJoins ) {
|
||||||
|
final TableReference tableReference = tableGroupJoin.getJoinedGroup()
|
||||||
|
.resolveTableReference( navigablePath, tableExpression, allowFkOptimization );
|
||||||
|
if ( tableReference != null ) {
|
||||||
|
return tableReference;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
if ( tableGroupJoins != null ) {
|
if ( tableGroupJoins != null ) {
|
||||||
for ( TableGroupJoin tableGroupJoin : tableGroupJoins ) {
|
for ( TableGroupJoin tableGroupJoin : tableGroupJoins ) {
|
||||||
final TableReference tableReference = tableGroupJoin.getJoinedGroup()
|
final TableReference tableReference = tableGroupJoin.getJoinedGroup()
|
||||||
|
|
|
@ -66,13 +66,13 @@ public class EntityCollectionPartTableGroup implements TableGroup {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean canUseInnerJoins() {
|
public List<TableGroupJoin> getNestedTableGroupJoins() {
|
||||||
return collectionTableGroup.canUseInnerJoins();
|
return collectionTableGroup.getNestedTableGroupJoins();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean hasTableGroupJoins() {
|
public boolean canUseInnerJoins() {
|
||||||
return collectionTableGroup.hasTableGroupJoins();
|
return collectionTableGroup.canUseInnerJoins();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -80,11 +80,21 @@ public class EntityCollectionPartTableGroup implements TableGroup {
|
||||||
collectionTableGroup.addTableGroupJoin( join );
|
collectionTableGroup.addTableGroupJoin( join );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addNestedTableGroupJoin(TableGroupJoin join) {
|
||||||
|
collectionTableGroup.addNestedTableGroupJoin( join );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitTableGroupJoins(Consumer<TableGroupJoin> consumer) {
|
public void visitTableGroupJoins(Consumer<TableGroupJoin> consumer) {
|
||||||
collectionTableGroup.visitTableGroupJoins( consumer );
|
collectionTableGroup.visitTableGroupJoins( consumer );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitNestedTableGroupJoins(Consumer<TableGroupJoin> consumer) {
|
||||||
|
collectionTableGroup.visitNestedTableGroupJoins( consumer );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void applyAffectedTableNames(Consumer<String> nameCollector) {
|
public void applyAffectedTableNames(Consumer<String> nameCollector) {
|
||||||
collectionTableGroup.applyAffectedTableNames( nameCollector );
|
collectionTableGroup.applyAffectedTableNames( nameCollector );
|
||||||
|
|
|
@ -68,6 +68,7 @@ public class EmbeddableFetchImpl extends AbstractFetchParent implements Embeddab
|
||||||
null,
|
null,
|
||||||
nullable ? SqlAstJoinType.LEFT : SqlAstJoinType.INNER,
|
nullable ? SqlAstJoinType.LEFT : SqlAstJoinType.INNER,
|
||||||
true,
|
true,
|
||||||
|
false,
|
||||||
creationState.getSqlAstCreationState()
|
creationState.getSqlAstCreationState()
|
||||||
);
|
);
|
||||||
return tableGroupJoin.getJoinedGroup();
|
return tableGroupJoin.getJoinedGroup();
|
||||||
|
|
|
@ -54,6 +54,7 @@ public class EmbeddableResultImpl<T> extends AbstractFetchParent implements Embe
|
||||||
resultVariable,
|
resultVariable,
|
||||||
SqlAstJoinType.INNER,
|
SqlAstJoinType.INNER,
|
||||||
true,
|
true,
|
||||||
|
false,
|
||||||
creationState.getSqlAstCreationState()
|
creationState.getSqlAstCreationState()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,6 @@ import java.util.List;
|
||||||
import org.hibernate.HibernateException;
|
import org.hibernate.HibernateException;
|
||||||
import org.hibernate.QueryException;
|
import org.hibernate.QueryException;
|
||||||
import org.hibernate.dialect.DerbyDialect;
|
import org.hibernate.dialect.DerbyDialect;
|
||||||
import org.hibernate.dialect.TiDBDialect;
|
|
||||||
import org.hibernate.query.Query;
|
import org.hibernate.query.Query;
|
||||||
|
|
||||||
import org.hibernate.testing.TestForIssue;
|
import org.hibernate.testing.TestForIssue;
|
||||||
|
@ -115,7 +114,6 @@ public class WithClauseTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@SkipForDialect(dialectClass = TiDBDialect.class, reason = "TiDB db does not support subqueries for ON condition")
|
|
||||||
public void testWithClauseWithImplicitJoin(SessionFactoryScope scope) {
|
public void testWithClauseWithImplicitJoin(SessionFactoryScope scope) {
|
||||||
scope.inTransaction(
|
scope.inTransaction(
|
||||||
(session) -> {
|
(session) -> {
|
||||||
|
|
|
@ -100,7 +100,7 @@ public class SmokeTests {
|
||||||
|
|
||||||
assertThat( rootTableGroup.getTableReferenceJoins().size(), is( 0 ) );
|
assertThat( rootTableGroup.getTableReferenceJoins().size(), is( 0 ) );
|
||||||
|
|
||||||
assertThat( rootTableGroup.hasTableGroupJoins(), is( false ) );
|
assertThat( rootTableGroup.getTableGroupJoins().isEmpty(), is( true ) );
|
||||||
|
|
||||||
|
|
||||||
// `s` is the "alias stem" for `SimpleEntity` and as it is the first entity with that stem in
|
// `s` is the "alias stem" for `SimpleEntity` and as it is the first entity with that stem in
|
||||||
|
@ -159,7 +159,7 @@ public class SmokeTests {
|
||||||
|
|
||||||
assertThat( rootTableGroup.getTableReferenceJoins().size(), is( 0 ) );
|
assertThat( rootTableGroup.getTableReferenceJoins().size(), is( 0 ) );
|
||||||
|
|
||||||
assertThat( rootTableGroup.hasTableGroupJoins(), is( false ) );
|
assertThat( rootTableGroup.getTableGroupJoins().isEmpty(), is( true ) );
|
||||||
|
|
||||||
|
|
||||||
// `s` is the "alias stem" for `SimpleEntity` and as it is the first entity with that stem in
|
// `s` is the "alias stem" for `SimpleEntity` and as it is the first entity with that stem in
|
||||||
|
|
|
@ -174,13 +174,13 @@ public class OrderByFragmentFunction extends AbstractSqmFunctionDescriptor {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean canUseInnerJoins() {
|
public List<TableGroupJoin> getNestedTableGroupJoins() {
|
||||||
return delegate.canUseInnerJoins();
|
return delegate.getNestedTableGroupJoins();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean hasTableGroupJoins() {
|
public boolean canUseInnerJoins() {
|
||||||
return delegate.hasTableGroupJoins();
|
return delegate.canUseInnerJoins();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -188,11 +188,21 @@ public class OrderByFragmentFunction extends AbstractSqmFunctionDescriptor {
|
||||||
delegate.addTableGroupJoin( join );
|
delegate.addTableGroupJoin( join );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addNestedTableGroupJoin(TableGroupJoin join) {
|
||||||
|
delegate.addNestedTableGroupJoin( join );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitTableGroupJoins(Consumer<TableGroupJoin> consumer) {
|
public void visitTableGroupJoins(Consumer<TableGroupJoin> consumer) {
|
||||||
delegate.visitTableGroupJoins( consumer );
|
delegate.visitTableGroupJoins( consumer );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitNestedTableGroupJoins(Consumer<TableGroupJoin> consumer) {
|
||||||
|
delegate.visitNestedTableGroupJoins( consumer );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void applyAffectedTableNames(Consumer<String> nameCollector) {
|
public void applyAffectedTableNames(Consumer<String> nameCollector) {
|
||||||
delegate.applyAffectedTableNames( nameCollector );
|
delegate.applyAffectedTableNames( nameCollector );
|
||||||
|
|
Loading…
Reference in New Issue