Implement table group rendering for real table groups and get rid of canInnerJoin flags due to that

This commit is contained in:
Christian Beikov 2021-04-01 18:00:09 +02:00
parent 159135ea89
commit c285f604f3
27 changed files with 81 additions and 196 deletions

View File

@ -83,7 +83,6 @@ import static org.hibernate.cfg.AvailableSettings.BATCH_VERSIONED_DATA;
import static org.hibernate.cfg.AvailableSettings.CACHE_REGION_PREFIX;
import static org.hibernate.cfg.AvailableSettings.CALLABLE_NAMED_PARAMS_ENABLED;
import static org.hibernate.cfg.AvailableSettings.CHECK_NULLABILITY;
import static org.hibernate.cfg.AvailableSettings.COLLECTION_JOIN_SUBQUERY;
import static org.hibernate.cfg.AvailableSettings.CONNECTION_HANDLING;
import static org.hibernate.cfg.AvailableSettings.CONVENTIONAL_JAVA_CONSTANTS;
import static org.hibernate.cfg.AvailableSettings.CRITERIA_LITERAL_HANDLING_MODE;
@ -221,7 +220,6 @@ public class SessionFactoryOptionsBuilder implements SessionFactoryOptions {
private boolean namedQueryStartupCheckingEnabled;
private boolean conventionalJavaConstants;
private final boolean procedureParameterNullPassingEnabled;
private final boolean collectionJoinSubqueryRewriteEnabled;
private final boolean omitJoinOfSuperclassTablesEnabled;
private final int preferredSqlTypeCodeForBoolean;
@ -411,7 +409,6 @@ public class SessionFactoryOptionsBuilder implements SessionFactoryOptions {
this.conventionalJavaConstants = cfgService.getSetting(
CONVENTIONAL_JAVA_CONSTANTS, BOOLEAN, true );
this.procedureParameterNullPassingEnabled = cfgService.getSetting( PROCEDURE_NULL_PARAM_PASSING, BOOLEAN, false );
this.collectionJoinSubqueryRewriteEnabled = cfgService.getSetting( COLLECTION_JOIN_SUBQUERY, BOOLEAN, true );
this.omitJoinOfSuperclassTablesEnabled = cfgService.getSetting( OMIT_JOIN_OF_SUPERCLASS_TABLES, BOOLEAN, true );
this.preferredSqlTypeCodeForBoolean = ConfigurationHelper.getPreferredSqlTypeCodeForBoolean( serviceRegistry );
@ -1003,11 +1000,6 @@ public class SessionFactoryOptionsBuilder implements SessionFactoryOptions {
return procedureParameterNullPassingEnabled;
}
@Override
public boolean isCollectionJoinSubqueryRewriteEnabled() {
return collectionJoinSubqueryRewriteEnabled;
}
@Override
public boolean isSecondLevelCacheEnabled() {
return secondLevelCacheEnabled;

View File

@ -244,11 +244,6 @@ public class AbstractDelegatingSessionFactoryOptions implements SessionFactoryOp
return delegate.isProcedureParameterNullPassingEnabled();
}
@Override
public boolean isCollectionJoinSubqueryRewriteEnabled() {
return delegate.isCollectionJoinSubqueryRewriteEnabled();
}
@Override
public boolean isAllowOutOfTransactionUpdateOperations() {
return delegate.isAllowOutOfTransactionUpdateOperations();

View File

@ -259,8 +259,6 @@ public interface SessionFactoryOptions extends QueryEngineOptions {
boolean isProcedureParameterNullPassingEnabled();
boolean isCollectionJoinSubqueryRewriteEnabled();
boolean isAllowOutOfTransactionUpdateOperations();
boolean isReleaseResourcesOnCloseEnabled();

View File

@ -176,7 +176,6 @@ public abstract class AbstractNaturalIdLoader<T> implements NaturalIdLoader<T> {
final TableGroup rootTableGroup = entityDescriptor.createRootTableGroup(
entityPath,
null,
true,
lockMode,
() -> rootQuerySpec::applyPredicate,
sqlAstCreationState,

View File

@ -91,7 +91,6 @@ class DatabaseSnapshotExecutor {
final TableGroup rootTableGroup = entityDescriptor.createRootTableGroup(
rootPath,
null,
true,
LockMode.NONE,
() -> rootQuerySpec::applyPredicate,
state,

View File

@ -376,7 +376,6 @@ public class LoaderSelectBuilder {
final TableGroup rootTableGroup = loadable.createRootTableGroup(
rootNavigablePath,
null,
true,
lockOptions.getLockMode(),
() -> rootQuerySpec::applyPredicate,
sqlAstCreationState,
@ -828,7 +827,6 @@ public class LoaderSelectBuilder {
final TableGroup rootTableGroup = loadable.createRootTableGroup(
rootNavigablePath,
null,
true,
lockOptions.getLockMode(),
() -> rootQuerySpec::applyPredicate,
sqlAstCreationState,

View File

@ -40,7 +40,6 @@ public interface Loadable extends ModelPart, RootTableGroupProducer {
default TableGroup createRootTableGroup(
NavigablePath navigablePath,
String explicitSourceAlias,
boolean canUseInnerJoins,
LockMode lockMode,
Supplier<Consumer<Predicate>> additionalPredicateCollectorAccess,
SqlAstCreationState creationState, SqlAstCreationContext creationContext) {

View File

@ -273,7 +273,6 @@ public interface EntityMappingType extends ManagedMappingType, EntityValuedModel
default TableGroup createRootTableGroup(
NavigablePath navigablePath,
String explicitSourceAlias,
boolean canUseInnerJoins,
LockMode lockMode,
Supplier<Consumer<Predicate>> additionalPredicateCollectorAccess,
SqlAstCreationState creationState,
@ -281,7 +280,6 @@ public interface EntityMappingType extends ManagedMappingType, EntityValuedModel
return getEntityPersister().createRootTableGroup(
navigablePath,
explicitSourceAlias,
canUseInnerJoins,
lockMode,
additionalPredicateCollectorAccess,
creationState,
@ -303,7 +301,6 @@ public interface EntityMappingType extends ManagedMappingType, EntityValuedModel
String joinTableExpression,
SqlAliasBase sqlAliasBase,
TableReference lhs,
boolean canUseInnerJoin,
SqlExpressionResolver sqlExpressionResolver,
SqlAstCreationContext creationContext) {
throw new UnsupportedOperationException(

View File

@ -592,8 +592,6 @@ public class PluralAttributeMappingImpl
SqlAstCreationContext creationContext) {
final TableGroup tableGroup = createOneToManyTableGroup(
navigablePath,
sqlAstJoinType == SqlAstJoinType.INNER
&& !getAttributeMetadataAccess().resolveAttributeMetadata( null ).isNullable(),
lockMode,
aliasBaseGenerator,
sqlExpressionResolver,
@ -620,7 +618,6 @@ public class PluralAttributeMappingImpl
private TableGroup createOneToManyTableGroup(
NavigablePath navigablePath,
boolean canUseInnerJoins,
LockMode lockMode,
SqlAliasBaseGenerator aliasBaseGenerator,
SqlExpressionResolver sqlExpressionResolver,
@ -649,13 +646,13 @@ public class PluralAttributeMappingImpl
this,
lockMode,
primaryTableReference,
true,
sqlAliasBase,
entityMappingType::containsTableReference,
(tableExpression, tg) -> entityMappingType.createTableReferenceJoin(
tableExpression,
sqlAliasBase,
primaryTableReference,
canUseInnerJoins,
sqlExpressionResolver,
creationContext
),
@ -675,8 +672,6 @@ public class PluralAttributeMappingImpl
SqlAstCreationContext creationContext) {
final TableGroup tableGroup = createCollectionTableGroup(
navigablePath,
sqlAstJoinType == SqlAstJoinType.INNER
&& !getAttributeMetadataAccess().resolveAttributeMetadata( null ).isNullable(),
lockMode,
aliasBaseGenerator,
sqlExpressionResolver,
@ -703,7 +698,6 @@ public class PluralAttributeMappingImpl
private TableGroup createCollectionTableGroup(
NavigablePath navigablePath,
boolean canUseInnerJoin,
LockMode lockMode,
SqlAliasBaseGenerator aliasBaseGenerator,
SqlExpressionResolver sqlExpressionResolver,
@ -746,13 +740,7 @@ public class PluralAttributeMappingImpl
final TableReference elementAssociatedPrimaryTable;
final Function<TableGroup, TableReferenceJoin> elementTableGroupFinalizer;
// todo (6.0) : not sure it is
final boolean elementUseInnerJoin;
if ( elementDescriptorEntityMappingType != null ) {
elementUseInnerJoin = canUseInnerJoin && !getAttributeMetadataAccess()
.resolveAttributeMetadata( elementDescriptorEntityMappingType ).isNullable();
final SqlAstJoinType joinType = elementUseInnerJoin
? SqlAstJoinType.INNER
: SqlAstJoinType.LEFT;
elementAssociatedPrimaryTable = elementDescriptorEntityMappingType.createPrimaryTableReference(
sqlAliasBase,
sqlExpressionResolver,
@ -764,25 +752,18 @@ public class PluralAttributeMappingImpl
creationContext,
collectionTableReference,
elementAssociatedPrimaryTable,
joinType,
SqlAstJoinType.INNER,
elementFkDescriptor
);
}
else {
elementAssociatedPrimaryTable = null;
elementTableGroupFinalizer = null;
elementUseInnerJoin = false;
}
TableReference indexAssociatedPrimaryTable;
final Function<TableGroup, TableReferenceJoin> indexTableGroupFinalizer;
final boolean indexUseInnerJoin;
if ( indexDescriptorEntityMappingType != null ) {
indexUseInnerJoin = canUseInnerJoin && !getAttributeMetadataAccess()
.resolveAttributeMetadata( indexDescriptorEntityMappingType ).isNullable();
final SqlAstJoinType joinType = indexUseInnerJoin
? SqlAstJoinType.INNER
: SqlAstJoinType.LEFT;
indexAssociatedPrimaryTable = indexDescriptorEntityMappingType.createPrimaryTableReference(
sqlAliasBase,
sqlExpressionResolver,
@ -794,14 +775,13 @@ public class PluralAttributeMappingImpl
creationContext,
collectionTableReference,
indexAssociatedPrimaryTable,
joinType,
SqlAstJoinType.INNER,
indexFkDescriptor
);
}
else {
indexAssociatedPrimaryTable = null;
indexTableGroupFinalizer = null;
indexUseInnerJoin = false;
}
if ( elementDescriptorEntityMappingType != null || indexDescriptorEntityMappingType != null ) {
@ -815,7 +795,6 @@ public class PluralAttributeMappingImpl
elementDescriptorEntityMappingType,
elementAssociatedPrimaryTable,
elementTableGroupFinalizer,
elementUseInnerJoin,
tableExpression,
tableGroup
);
@ -829,7 +808,6 @@ public class PluralAttributeMappingImpl
indexDescriptorEntityMappingType,
indexAssociatedPrimaryTable,
indexTableGroupFinalizer,
indexUseInnerJoin,
tableExpression,
tableGroup
);
@ -850,6 +828,7 @@ public class PluralAttributeMappingImpl
this,
lockMode,
collectionTableReference,
true,
sqlAliasBase,
tableReferenceJoinNameChecker,
tableReferenceJoinCreator,
@ -866,7 +845,6 @@ public class PluralAttributeMappingImpl
EntityMappingType elementDescriptorEntityMappingType,
TableReference elementAssociatedPrimaryTable,
Function<TableGroup, TableReferenceJoin> elementTableGroupFinalizer,
boolean useInnerJoin,
String tableExpression, TableGroup tableGroup) {
if ( elementAssociatedPrimaryTable.getTableExpression().equals( tableExpression ) ) {
TableReferenceJoin tableReferenceJoin = elementTableGroupFinalizer.apply( tableGroup );
@ -883,7 +861,6 @@ public class PluralAttributeMappingImpl
tableExpression,
sqlAliasBase,
elementAssociatedPrimaryTable,
useInnerJoin,
sqlExpressionResolver,
creationContext
);
@ -933,7 +910,6 @@ public class PluralAttributeMappingImpl
public TableGroup createRootTableGroup(
NavigablePath navigablePath,
String explicitSourceAlias,
boolean canUseInnerJoins,
LockMode lockMode,
Supplier<Consumer<Predicate>> additionalPredicateCollectorAccess,
SqlAstCreationState creationState,
@ -941,7 +917,6 @@ public class PluralAttributeMappingImpl
if ( getCollectionDescriptor().isOneToMany() ) {
return createOneToManyTableGroup(
navigablePath,
canUseInnerJoins,
lockMode,
creationState.getSqlAliasBaseGenerator(),
creationState.getSqlExpressionResolver(),
@ -951,7 +926,6 @@ public class PluralAttributeMappingImpl
else {
return createCollectionTableGroup(
navigablePath,
canUseInnerJoins,
lockMode,
creationState.getSqlAliasBaseGenerator(),
creationState.getSqlExpressionResolver(),

View File

@ -597,13 +597,13 @@ public class ToOneAttributeMapping
this,
lockMode,
primaryTableReference,
false,
sqlAliasBase,
(tableExpression) -> getEntityMappingType().containsTableReference( tableExpression ),
(tableExpression, tg) -> getEntityMappingType().createTableReferenceJoin(
tableExpression,
sqlAliasBase,
primaryTableReference,
false,
sqlExpressionResolver,
creationContext
),

View File

@ -1361,7 +1361,6 @@ public abstract class AbstractEntityPersister
public TableGroup createRootTableGroup(
NavigablePath navigablePath,
String explicitSourceAlias,
boolean canUseInnerJoins,
LockMode lockMode,
Supplier<Consumer<Predicate>> additionalPredicateCollectorAccess,
SqlAstCreationState creationState,
@ -1381,6 +1380,7 @@ public abstract class AbstractEntityPersister
this,
lockMode,
primaryTableReference,
true,
sqlAliasBase,
(tableExpression) -> ArrayHelper.contains( getSubclassTableNames(), tableExpression ),
(tableExpression, tableGroup) -> {
@ -1398,7 +1398,6 @@ public abstract class AbstractEntityPersister
return new TableReferenceJoin(
determineSubclassTableJoinType(
i,
canUseInnerJoins,
true,
Collections.emptySet()
),
@ -1433,7 +1432,6 @@ public abstract class AbstractEntityPersister
String joinTableExpression,
SqlAliasBase sqlAliasBase,
TableReference lhs,
boolean canUseInnerJoin,
SqlExpressionResolver sqlExpressionResolver,
SqlAstCreationContext creationContext) {
for ( int i = 1; i < getSubclassTableSpan(); i++ ) {
@ -1443,7 +1441,7 @@ public abstract class AbstractEntityPersister
lhs,
joinTableExpression,
sqlAliasBase,
determineSubclassTableJoinType( i, canUseInnerJoin, true, Collections.emptySet() ),
determineSubclassTableJoinType( i, true, Collections.emptySet() ),
getSubclassTableKeyColumns( i ),
sqlExpressionResolver
);
@ -4340,12 +4338,10 @@ public abstract class AbstractEntityPersister
protected SqlAstJoinType determineSubclassTableJoinType(
int subclassTableNumber,
boolean canInnerJoin,
boolean includeSubclasses,
Set<String> treatAsDeclarations) {
if ( isClassOrSuperclassTable( subclassTableNumber ) ) {
final boolean shouldInnerJoin = canInnerJoin
&& !isInverseTable( subclassTableNumber )
final boolean shouldInnerJoin = !isInverseTable( subclassTableNumber )
&& !isNullableTable( subclassTableNumber );
// the table is either this persister's driving table or (one of) its super class persister's driving
// tables which can be inner joined as long as the `shouldInnerJoin` condition resolves to true

View File

@ -902,7 +902,6 @@ public class SingleTableEntityPersister extends AbstractEntityPersister {
public TableGroup createRootTableGroup(
NavigablePath navigablePath,
String explicitSourceAlias,
boolean canUseInnerJoins,
LockMode lockMode,
Supplier<Consumer<Predicate>> additionalPredicateCollectorAccess,
SqlAstCreationState creationState,
@ -910,7 +909,6 @@ public class SingleTableEntityPersister extends AbstractEntityPersister {
final TableGroup tableGroup = super.createRootTableGroup(
navigablePath,
explicitSourceAlias,
canUseInnerJoins,
lockMode,
additionalPredicateCollectorAccess,
creationState, creationContext

View File

@ -223,7 +223,6 @@ public class UnionSubclassEntityPersister extends AbstractEntityPersister {
public TableGroup createRootTableGroup(
NavigablePath navigablePath,
String explicitSourceAlias,
boolean canUseInnerJoins,
LockMode lockMode,
Supplier<Consumer<Predicate>> additionalPredicateCollectorAccess,
SqlAstCreationState creationState,

View File

@ -81,7 +81,6 @@ public class CompleteResultBuilderEntityJpa implements CompleteResultBuilderEnti
np -> entityDescriptor.createRootTableGroup(
navigablePath,
null,
false,
lockMode,
() -> predicate -> {},
impl.getSqlAstCreationState(),

View File

@ -73,7 +73,6 @@ public class CompleteResultBuilderEntityStandard implements CompleteResultBuilde
np -> entityDescriptor.createRootTableGroup(
navigablePath,
null,
false,
lockMode,
() -> predicate -> {},
impl,

View File

@ -60,7 +60,6 @@ public class ImplicitModelPartResultBuilderEntity
return modelPart.getEntityMappingType().createRootTableGroup(
navigablePath,
null,
false,
LockMode.READ,
() -> predicate -> {
},

View File

@ -66,6 +66,7 @@ import org.hibernate.query.sqm.tree.from.SqmCrossJoin;
import org.hibernate.query.sqm.tree.from.SqmEntityJoin;
import org.hibernate.query.sqm.tree.from.SqmFrom;
import org.hibernate.query.sqm.tree.from.SqmFromClause;
import org.hibernate.query.sqm.tree.from.SqmQualifiedJoin;
import org.hibernate.query.sqm.tree.from.SqmRoot;
import org.hibernate.query.sqm.tree.insert.SqmInsertSelectStatement;
import org.hibernate.query.sqm.tree.insert.SqmInsertValuesStatement;
@ -503,45 +504,55 @@ public class SqmTreePrinter implements SemanticQueryWalker<Object> {
return null;
}
private boolean inJoinPredicate;
private void processJoinPredicate(SqmQualifiedJoin<?, ?> joinedFromElement) {
if ( joinedFromElement.getJoinPredicate() != null ) {
boolean oldInJoinPredicate = inJoinPredicate;
inJoinPredicate = true;
processStanza(
"on",
() -> joinedFromElement.getJoinPredicate().accept( this )
);
inJoinPredicate = oldInJoinPredicate;
}
}
@Override
public Object visitQualifiedEntityJoin(SqmEntityJoin joinedFromElement) {
processStanza(
"entity",
'`' + joinedFromElement.getNavigablePath().getFullPath() + '`',
() -> {
if ( joinedFromElement.getJoinPredicate() != null ) {
processStanza(
"on",
() -> joinedFromElement.getJoinPredicate().accept( this )
);
if ( inJoinPredicate ) {
logWithIndentation( "-> [joined-path] - `%s`", joinedFromElement.getNavigablePath().getFullPath() );
}
else {
processStanza(
"entity",
'`' + joinedFromElement.getNavigablePath().getFullPath() + '`',
() -> {
processJoinPredicate( joinedFromElement );
processJoins( joinedFromElement );
}
processJoins( joinedFromElement );
}
);
);
}
return null;
}
@Override
public Object visitQualifiedAttributeJoin(SqmAttributeJoin joinedFromElement) {
processStanza(
"attribute",
'`' + joinedFromElement.getNavigablePath().getFullPath() + '`',
() -> {
logIndented( "[fetched = " + joinedFromElement.isFetched() + ']' );
if ( inJoinPredicate ) {
logWithIndentation( "-> [joined-path] - `%s`", joinedFromElement.getNavigablePath().getFullPath() );
}
else {
processStanza(
"attribute",
'`' + joinedFromElement.getNavigablePath().getFullPath() + '`',
() -> {
logIndented( "[fetched = " + joinedFromElement.isFetched() + ']' );
if ( joinedFromElement.getJoinPredicate() != null ) {
processStanza(
"on",
() -> joinedFromElement.getJoinPredicate().accept( this )
);
processJoinPredicate( joinedFromElement );
processJoins( joinedFromElement );
}
processJoins( joinedFromElement );
}
);
);
}
return null;
}

View File

@ -81,7 +81,6 @@ public class MultiTableSqmMutationConverter extends BaseSqmToSqlAstConverter<Sta
this.mutatingTableGroup = mutatingEntityDescriptor.createRootTableGroup(
navigablePath,
mutatingEntityExplicitAlias,
true,
LockMode.PESSIMISTIC_WRITE,
() -> predicate -> {
},

View File

@ -565,7 +565,6 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
final TableGroup rootTableGroup = entityDescriptor.createRootTableGroup(
rootPath,
sqmStatement.getRoot().getAlias(),
false,
LockMode.WRITE,
() -> predicate -> additionalRestrictions = predicate,
this,
@ -825,7 +824,6 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
final TableGroup rootTableGroup = entityDescriptor.createRootTableGroup(
rootPath,
statement.getRoot().getAlias(),
false,
LockMode.WRITE,
() -> predicate -> additionalRestrictions = predicate,
this,
@ -906,7 +904,6 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
final TableGroup rootTableGroup = entityDescriptor.createRootTableGroup(
rootPath,
sqmStatement.getTarget().getExplicitAlias(),
false,
LockMode.WRITE,
() -> predicate -> additionalRestrictions = predicate,
this,
@ -1006,7 +1003,6 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
final TableGroup rootTableGroup = entityDescriptor.createRootTableGroup(
rootPath,
sqmStatement.getTarget().getExplicitAlias(),
false,
LockMode.WRITE,
() -> predicate -> additionalRestrictions = predicate,
this,
@ -1702,7 +1698,6 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
tableGroup = entityDescriptor.createRootTableGroup(
sqmRoot.getNavigablePath(),
sqmRoot.getExplicitAlias(),
true,
LockMode.NONE,
() -> predicate -> {},
this,
@ -1767,7 +1762,6 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
tableGroup = entityDescriptor.createRootTableGroup(
sqmRoot.getNavigablePath(),
sqmRoot.getExplicitAlias(),
true,
LockMode.NONE,
() -> predicate -> additionalRestrictions = SqlAstTreeHelper.combinePredicates(
additionalRestrictions,
@ -1919,7 +1913,6 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
final TableGroup tableGroup = entityDescriptor.createRootTableGroup(
sqmJoin.getNavigablePath(),
sqmJoin.getExplicitAlias(),
true,
determineLockMode( sqmJoin.getExplicitAlias() ),
() -> predicate -> additionalRestrictions = SqlAstTreeHelper.combinePredicates(
additionalRestrictions,
@ -1949,7 +1942,6 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
final TableGroup tableGroup = entityDescriptor.createRootTableGroup(
sqmJoin.getNavigablePath(),
sqmJoin.getExplicitAlias(),
true,
determineLockMode( sqmJoin.getExplicitAlias() ),
() -> predicate -> additionalRestrictions = SqlAstTreeHelper.combinePredicates(
additionalRestrictions,
@ -3650,7 +3642,6 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
final TableGroup tableGroup = collectionPart.createRootTableGroup(
pluralPath.getNavigablePath(),
null,
true,
LockOptions.NONE.getLockMode(),
() -> subQuerySpec::applyPredicate,
this,
@ -3719,7 +3710,6 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
final TableGroup tableGroup = mappingModelExpressable.createRootTableGroup(
pluralPartPath.getNavigablePath(),
null,
true,
LockOptions.NONE.getLockMode(),
() -> subQuerySpec::applyPredicate,
this,
@ -3868,7 +3858,6 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
final TableGroup tableGroup = mappingModelExpressable.createRootTableGroup(
pluralPath.getNavigablePath(),
null,
true,
LockOptions.NONE.getLockMode(),
() -> subQuerySpec::applyPredicate,
this,

View File

@ -2533,26 +2533,28 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
}
protected void renderTableGroup(TableGroup tableGroup, Predicate predicate) {
// NOTE : commented out blocks render the TableGroup as a CTE
// if ( tableGroup.getGroupAlias() != null ) {
// sqlAppender.appendSql( OPEN_PARENTHESIS );
// }
// Without reference joins, even a real table group does not need parenthesis
final boolean realTableGroup = tableGroup.isRealTableGroup()
&& CollectionHelper.isNotEmpty( tableGroup.getTableReferenceJoins() );
if ( realTableGroup ) {
appendSql( '(' );
}
renderTableReference( tableGroup.getPrimaryTableReference() );
if ( realTableGroup ) {
renderTableReferenceJoins( tableGroup );
appendSql( ')' );
}
appendSql( " on " );
predicate.accept( this );
renderTableReferenceJoins( tableGroup );
// if ( tableGroup.getGroupAlias() != null ) {
// sqlAppender.appendSql( CLOSE_PARENTHESIS );
// sqlAppender.appendSql( AS_KEYWORD );
// sqlAppender.appendSql( tableGroup.getGroupAlias() );
// }
if ( !realTableGroup ) {
renderTableReferenceJoins( tableGroup );
}
processTableGroupJoins( tableGroup );
ModelPartContainer modelPart = tableGroup.getModelPart();
if ( modelPart instanceof AbstractEntityPersister ) {
String[] querySpaces = (String[]) ( (AbstractEntityPersister) modelPart ).getQuerySpaces();
@ -2625,7 +2627,7 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
else {
appendSql( EMPTY_STRING );
SqlAstJoinType joinType = tableGroupJoin.getJoinType();
if ( joinType == SqlAstJoinType.INNER && !joinedGroup.getTableReferenceJoins().isEmpty() ) {
if ( !joinedGroup.isRealTableGroup() && joinType == SqlAstJoinType.INNER && !joinedGroup.getTableReferenceJoins().isEmpty() ) {
joinType = SqlAstJoinType.LEFT;
}
appendSql( joinType.getText() );

View File

@ -29,7 +29,6 @@ public interface RootTableGroupProducer extends TableGroupProducer, ModelPartCon
TableGroup createRootTableGroup(
NavigablePath navigablePath,
String explicitSourceAlias,
boolean canUseInnerJoins,
LockMode lockMode,
Supplier<Consumer<Predicate>> additionalPredicateCollectorAccess,
SqlAstCreationState creationState, SqlAstCreationContext creationContext);

View File

@ -25,6 +25,7 @@ public class StandardTableGroup extends AbstractTableGroup {
private final TableReference primaryTableReference;
private final Predicate<String> tableReferenceJoinNameChecker;
private final BiFunction<String,TableGroup,TableReferenceJoin> tableReferenceJoinCreator;
private final boolean realTableGroup;
private List<TableReferenceJoin> tableJoins;
@ -37,6 +38,7 @@ public class StandardTableGroup extends AbstractTableGroup {
SessionFactoryImplementor sessionFactory) {
super( navigablePath, tableGroupProducer, lockMode, sqlAliasBase, sessionFactory );
this.primaryTableReference = primaryTableReference;
this.realTableGroup = false;
this.tableJoins = Collections.emptyList();
this.tableReferenceJoinCreator = null;
this.tableReferenceJoinNameChecker = s -> {
@ -54,12 +56,14 @@ public class StandardTableGroup extends AbstractTableGroup {
TableGroupProducer tableGroupProducer,
LockMode lockMode,
TableReference primaryTableReference,
boolean realTableGroup,
SqlAliasBase sqlAliasBase,
Predicate<String> tableReferenceJoinNameChecker,
BiFunction<String,TableGroup,TableReferenceJoin> tableReferenceJoinCreator,
BiFunction<String, TableGroup, TableReferenceJoin> tableReferenceJoinCreator,
SessionFactoryImplementor sessionFactory) {
super( navigablePath, tableGroupProducer, lockMode, sqlAliasBase, sessionFactory );
this.primaryTableReference = primaryTableReference;
this.realTableGroup = realTableGroup;
this.tableJoins = null;
this.tableReferenceJoinNameChecker = tableReferenceJoinNameChecker;
this.tableReferenceJoinCreator = tableReferenceJoinCreator;
@ -89,6 +93,11 @@ public class StandardTableGroup extends AbstractTableGroup {
return tableJoins == null ? Collections.emptyList() : tableJoins;
}
@Override
public boolean isRealTableGroup() {
return realTableGroup;
}
public void addTableReferenceJoin(TableReferenceJoin join) {
if ( tableJoins == null ) {
tableJoins = new ArrayList<>();

View File

@ -87,4 +87,8 @@ public interface TableGroup extends SqlAstNode, ColumnReferenceQualifier, SqmPat
}
boolean isInnerJoinPossible();
default boolean isRealTableGroup() {
return false;
}
}

View File

@ -791,7 +791,6 @@ public class DynamicFilterTest extends BaseNonConfigCoreFunctionalTestCase {
}
@Test
@FailureExpected(jiraKey = "none", message = "v6 imperfection")
public void testManyToManyFilterOnCriteria() {
inSession(
session -> {
@ -818,7 +817,6 @@ public class DynamicFilterTest extends BaseNonConfigCoreFunctionalTestCase {
}
@Test
@FailureExpected(jiraKey = "none", message = "v6 imperfection")
public void testManyToManyFilterOnLoad() {
inSession(
session -> {
@ -858,7 +856,6 @@ public class DynamicFilterTest extends BaseNonConfigCoreFunctionalTestCase {
}
@Test
@FailureExpected(jiraKey = "none", message = "v6 imperfection")
public void testManyToManyOnCollectionLoadAfterHQL() {
inSession(
session -> {
@ -882,7 +879,6 @@ public class DynamicFilterTest extends BaseNonConfigCoreFunctionalTestCase {
}
@Test
@FailureExpected(jiraKey = "none", message = "v6 imperfection")
public void testManyToManyFilterOnQuery() {
inSession(
session -> {

View File

@ -33,6 +33,7 @@ import org.junit.jupiter.api.Test;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
/**
* @author Chris Cranford
@ -76,7 +77,7 @@ public class ManyToManyWithDynamicFilterTest {
final User user = session.get( User.class, 1 );
assertNotNull( user );
assertThat( CollectionHelper.isNotEmpty( user.getRoles() ), is( true ) );
assertTrue( user.getRoles().isEmpty() );
} );
}

View File

@ -1,66 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.test.hql;
import java.util.List;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.ServiceRegistry;
import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.hibernate.testing.orm.junit.Setting;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import static org.junit.Assert.assertEquals;
/**
* Implementation of WithClauseTest.
*
* @author Steve Ebersole
*/
@ServiceRegistry(
settings = @Setting( name = AvailableSettings.COLLECTION_JOIN_SUBQUERY, value = "false" )
)
@DomainModel(
xmlMappings = {
"org/hibernate/test/hql/Animal.hbm.xml",
"org/hibernate/test/hql/SimpleEntityWithAssociation.hbm.xml",
}
)
@SessionFactory
public class CollectionJoinSubQueryWithClauseTest {
private final WithClauseTest.TestData data = new WithClauseTest.TestData();
@BeforeEach
public void createTestData(SessionFactoryScope scope) {
data.prepare( scope );
}
@AfterEach
public void dropTestData(SessionFactoryScope scope) {
data.cleanup( scope );
}
@Test
@TestForIssue(jiraKey = "HHH-11157")
public void testWithClauseAsNonSubqueryWithKey(SessionFactoryScope scope) {
scope.inTransaction(
(session) -> {
// Since family has a join table, we will first left join all family members and then do the WITH clause on the target entity table join
// Normally this produces 2 results which is wrong and can only be circumvented by converting the join table and target entity table join to a subquery
final String qry = "from Human h left join h.family as f with key(f) like 'son1' where h.description = 'father'";
List list = session.createQuery( qry ).list();
assertEquals( "sub-query rewriting of join table was not disabled", 2, list.size() );
}
);
}
}

View File

@ -200,7 +200,7 @@ public class WithClauseTest {
scope.inTransaction(
(s) -> {
// Just a stupid example that makes use of a column that isn't from the collection table or the target entity table
List list = s.createQuery( "from Human h join h.friends as friend left join h.family as f with key(f) = concat('son', cast(friend.intValue as string)) where h.description = 'father'" )
List list = s.createQuery( "select 1 from Human h join h.friends as friend left join h.family as f with key(f) = concat('son', cast(friend.intValue as string)) where h.description = 'father'" )
.list();
assertEquals( "subquery rewriting of join table did not take effect", 2, list.size() );
}