Implement table group rendering for real table groups and get rid of canInnerJoin flags due to that
This commit is contained in:
parent
159135ea89
commit
c285f604f3
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -259,8 +259,6 @@ public interface SessionFactoryOptions extends QueryEngineOptions {
|
|||
|
||||
boolean isProcedureParameterNullPassingEnabled();
|
||||
|
||||
boolean isCollectionJoinSubqueryRewriteEnabled();
|
||||
|
||||
boolean isAllowOutOfTransactionUpdateOperations();
|
||||
|
||||
boolean isReleaseResourcesOnCloseEnabled();
|
||||
|
|
|
@ -176,7 +176,6 @@ public abstract class AbstractNaturalIdLoader<T> implements NaturalIdLoader<T> {
|
|||
final TableGroup rootTableGroup = entityDescriptor.createRootTableGroup(
|
||||
entityPath,
|
||||
null,
|
||||
true,
|
||||
lockMode,
|
||||
() -> rootQuerySpec::applyPredicate,
|
||||
sqlAstCreationState,
|
||||
|
|
|
@ -91,7 +91,6 @@ class DatabaseSnapshotExecutor {
|
|||
final TableGroup rootTableGroup = entityDescriptor.createRootTableGroup(
|
||||
rootPath,
|
||||
null,
|
||||
true,
|
||||
LockMode.NONE,
|
||||
() -> rootQuerySpec::applyPredicate,
|
||||
state,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -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
|
||||
),
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -81,7 +81,6 @@ public class CompleteResultBuilderEntityJpa implements CompleteResultBuilderEnti
|
|||
np -> entityDescriptor.createRootTableGroup(
|
||||
navigablePath,
|
||||
null,
|
||||
false,
|
||||
lockMode,
|
||||
() -> predicate -> {},
|
||||
impl.getSqlAstCreationState(),
|
||||
|
|
|
@ -73,7 +73,6 @@ public class CompleteResultBuilderEntityStandard implements CompleteResultBuilde
|
|||
np -> entityDescriptor.createRootTableGroup(
|
||||
navigablePath,
|
||||
null,
|
||||
false,
|
||||
lockMode,
|
||||
() -> predicate -> {},
|
||||
impl,
|
||||
|
|
|
@ -60,7 +60,6 @@ public class ImplicitModelPartResultBuilderEntity
|
|||
return modelPart.getEntityMappingType().createRootTableGroup(
|
||||
navigablePath,
|
||||
null,
|
||||
false,
|
||||
LockMode.READ,
|
||||
() -> predicate -> {
|
||||
},
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -81,7 +81,6 @@ public class MultiTableSqmMutationConverter extends BaseSqmToSqlAstConverter<Sta
|
|||
this.mutatingTableGroup = mutatingEntityDescriptor.createRootTableGroup(
|
||||
navigablePath,
|
||||
mutatingEntityExplicitAlias,
|
||||
true,
|
||||
LockMode.PESSIMISTIC_WRITE,
|
||||
() -> predicate -> {
|
||||
},
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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() );
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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<>();
|
||||
|
|
|
@ -87,4 +87,8 @@ public interface TableGroup extends SqlAstNode, ColumnReferenceQualifier, SqmPat
|
|||
}
|
||||
|
||||
boolean isInnerJoinPossible();
|
||||
|
||||
default boolean isRealTableGroup() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 -> {
|
||||
|
|
|
@ -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() );
|
||||
} );
|
||||
}
|
||||
|
||||
|
|
|
@ -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() );
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
|
@ -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() );
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue