use of org.hibernate.sql.ast.tree.from.PluralTableGroup in project hibernate-orm by hibernate.
the class ToOneAttributeMapping method createTableGroupJoin.
@Override
public TableGroupJoin createTableGroupJoin(NavigablePath navigablePath, TableGroup lhs, String explicitSourceAlias, SqlAstJoinType requestedJoinType, boolean fetched, boolean addsPredicate, SqlAliasBaseGenerator aliasBaseGenerator, SqlExpressionResolver sqlExpressionResolver, FromClauseAccess fromClauseAccess, SqlAstCreationContext creationContext) {
// This is vital for the map key property check that comes next
assert !(lhs instanceof PluralTableGroup);
TableGroup parentTableGroup = lhs;
ModelPartContainer parentContainer = lhs.getModelPart();
StringBuilder embeddablePathSb = null;
// Traverse up embeddable table groups until we find a table group for a collection part
while (!(parentContainer instanceof CollectionPart)) {
if (parentContainer instanceof EmbeddableValuedModelPart) {
if (embeddablePathSb == null) {
embeddablePathSb = new StringBuilder();
}
embeddablePathSb.insert(0, parentContainer.getPartName() + ".");
parentTableGroup = fromClauseAccess.findTableGroup(parentTableGroup.getNavigablePath().getParent());
parentContainer = parentTableGroup.getModelPart();
} else {
break;
}
}
final SqlAstJoinType joinType;
if (requestedJoinType == null) {
joinType = SqlAstJoinType.INNER;
} else {
joinType = requestedJoinType;
}
// we check if this attribute is the map key property to reuse the existing index table group
if (CollectionPart.Nature.ELEMENT.getName().equals(parentTableGroup.getNavigablePath().getUnaliasedLocalName()) && !addsPredicate && (joinType == SqlAstJoinType.INNER || joinType == SqlAstJoinType.LEFT)) {
final PluralTableGroup pluralTableGroup = (PluralTableGroup) fromClauseAccess.findTableGroup(parentTableGroup.getNavigablePath().getParent());
final String indexPropertyName = pluralTableGroup.getModelPart().getIndexMetadata().getIndexPropertyName();
final String pathName;
if (embeddablePathSb != null) {
pathName = embeddablePathSb.append(getAttributeName()).toString();
} else {
pathName = getAttributeName();
}
if (pathName.equals(indexPropertyName)) {
final TableGroup indexTableGroup = pluralTableGroup.getIndexTableGroup();
// If this is the map key property, we can reuse the index table group
initializeIfNeeded(lhs, requestedJoinType, indexTableGroup);
return new TableGroupJoin(navigablePath, joinType, new MappedByTableGroup(navigablePath, this, indexTableGroup, fetched, pluralTableGroup, (np, tableExpression) -> {
if (!canUseParentTableGroup) {
return false;
}
NavigablePath path = np.getParent();
// Fast path
if (path != null && navigablePath.equals(path)) {
return targetKeyPropertyNames.contains(np.getUnaliasedLocalName()) && identifyingColumnsTableExpression.equals(tableExpression);
}
final StringBuilder sb = new StringBuilder(np.getFullPath().length());
sb.append(np.getUnaliasedLocalName());
while (path != null && !navigablePath.equals(path)) {
sb.insert(0, '.');
sb.insert(0, path.getUnaliasedLocalName());
path = path.getParent();
}
return path != null && navigablePath.equals(path) && targetKeyPropertyNames.contains(sb.toString()) && identifyingColumnsTableExpression.equals(tableExpression);
}), null);
}
}
final LazyTableGroup lazyTableGroup = createRootTableGroupJoin(navigablePath, lhs, explicitSourceAlias, requestedJoinType, fetched, null, aliasBaseGenerator, sqlExpressionResolver, fromClauseAccess, creationContext);
final TableGroupJoin join = new TableGroupJoin(navigablePath, joinType, lazyTableGroup, null);
final TableReference lhsTableReference = lhs.resolveTableReference(navigablePath, identifyingColumnsTableExpression);
lazyTableGroup.setTableGroupInitializerCallback(tableGroup -> join.applyPredicate(foreignKeyDescriptor.generateJoinPredicate(sideNature == ForeignKeyDescriptor.Nature.TARGET ? lhsTableReference : tableGroup.getPrimaryTableReference(), sideNature == ForeignKeyDescriptor.Nature.TARGET ? tableGroup.getPrimaryTableReference() : lhsTableReference, sqlExpressionResolver, creationContext)));
return join;
}
use of org.hibernate.sql.ast.tree.from.PluralTableGroup in project hibernate-orm by hibernate.
the class BaseSqmToSqlAstConverter method findActualTableGroup.
private TableGroup findActualTableGroup(TableGroup lhsTableGroup, SqmPath<?> path) {
final SqmPathSource<?> intermediatePathSource;
final SqmPath<?> lhs;
if (path instanceof SqmTreatedPath<?, ?>) {
lhs = ((SqmTreatedPath<?, ?>) path).getWrappedPath().getLhs();
} else {
lhs = path.getLhs();
}
intermediatePathSource = lhs == null ? null : lhs.getReferencedPathSource().getIntermediatePathSource(path.getReferencedPathSource());
if (intermediatePathSource == null) {
return lhsTableGroup;
}
// The only possible intermediate path source for now is the element path source for plural attributes
assert intermediatePathSource.getPathName().equals(CollectionPart.Nature.ELEMENT.getName());
final PluralTableGroup pluralTableGroup = (PluralTableGroup) lhsTableGroup;
return pluralTableGroup.getElementTableGroup();
}
use of org.hibernate.sql.ast.tree.from.PluralTableGroup in project hibernate-orm by hibernate.
the class BaseSqmToSqlAstConverter method consumeAttributeJoin.
private TableGroup consumeAttributeJoin(SqmAttributeJoin<?, ?> sqmJoin, TableGroup lhsTableGroup, TableGroup ownerTableGroup, boolean transitive) {
final SqmPathSource<?> pathSource = sqmJoin.getReferencedPathSource();
final SqmJoinType sqmJoinType = sqmJoin.getSqmJoinType();
final TableGroupJoin joinedTableGroupJoin;
final TableGroup joinedTableGroup;
final NavigablePath sqmJoinNavigablePath = sqmJoin.getNavigablePath();
final ModelPart modelPart = ownerTableGroup.getModelPart().findSubPart(pathSource.getPathName(), SqmMappingModelHelper.resolveExplicitTreatTarget(sqmJoin, this));
if (pathSource instanceof PluralPersistentAttribute) {
assert modelPart instanceof PluralAttributeMapping;
final PluralAttributeMapping pluralAttributeMapping = (PluralAttributeMapping) modelPart;
if (sqmJoin.isFetched()) {
containsCollectionFetches = true;
}
joinedTableGroupJoin = pluralAttributeMapping.createTableGroupJoin(sqmJoinNavigablePath, ownerTableGroup, sqmJoin.getExplicitAlias(), sqmJoinType.getCorrespondingSqlJoinType(), sqmJoin.isFetched(), sqmJoin.getJoinPredicate() != null, this);
joinedTableGroup = joinedTableGroupJoin.getJoinedGroup();
pluralAttributeMapping.applyBaseRestrictions((predicate) -> {
final PredicateCollector existing = collectionFilterPredicates.get(joinedTableGroup.getGroupAlias());
final PredicateCollector collector;
if (existing == null) {
collector = new PredicateCollector(predicate);
collectionFilterPredicates.put(joinedTableGroup.getGroupAlias(), collector);
} else {
collector = existing;
collector.applyPredicate(predicate);
}
}, joinedTableGroup, true, getLoadQueryInfluencers().getEnabledFilters(), null, this);
} else {
assert modelPart instanceof TableGroupJoinProducer;
joinedTableGroupJoin = ((TableGroupJoinProducer) modelPart).createTableGroupJoin(sqmJoinNavigablePath, ownerTableGroup, sqmJoin.getExplicitAlias(), sqmJoinType.getCorrespondingSqlJoinType(), sqmJoin.isFetched(), sqmJoin.getJoinPredicate() != null, this);
joinedTableGroup = joinedTableGroupJoin.getJoinedGroup();
// Left or inner singular attribute joins without a predicate can be safely optimized away
if (sqmJoin.getJoinPredicate() != null || sqmJoinType != SqmJoinType.INNER && sqmJoinType != SqmJoinType.LEFT) {
joinedTableGroup.getPrimaryTableReference();
}
}
lhsTableGroup.addTableGroupJoin(joinedTableGroupJoin);
getFromClauseIndex().register(sqmJoin, joinedTableGroup);
registerPluralTableGroupParts(joinedTableGroup);
// For joins we also need to register the table groups for the treats
if (joinedTableGroup instanceof PluralTableGroup) {
final PluralTableGroup pluralTableGroup = (PluralTableGroup) joinedTableGroup;
for (SqmFrom<?, ?> sqmTreat : sqmJoin.getSqmTreats()) {
if (pluralTableGroup.getElementTableGroup() != null) {
getFromClauseAccess().registerTableGroup(sqmTreat.getNavigablePath().append(CollectionPart.Nature.ELEMENT.getName()), pluralTableGroup.getElementTableGroup());
}
if (pluralTableGroup.getIndexTableGroup() != null) {
getFromClauseAccess().registerTableGroup(sqmTreat.getNavigablePath().append(CollectionPart.Nature.INDEX.getName()), pluralTableGroup.getIndexTableGroup());
}
}
} else {
for (SqmFrom<?, ?> sqmTreat : sqmJoin.getSqmTreats()) {
getFromClauseAccess().registerTableGroup(sqmTreat.getNavigablePath(), joinedTableGroup);
}
}
// add any additional join restrictions
if (sqmJoin.getJoinPredicate() != null) {
if (sqmJoin.isFetched()) {
QueryLogging.QUERY_MESSAGE_LOGGER.debugf("Join fetch [" + sqmJoinNavigablePath + "] is restricted");
}
final SqmJoin<?, ?> oldJoin = currentlyProcessingJoin;
currentlyProcessingJoin = sqmJoin;
joinedTableGroupJoin.applyPredicate(visitNestedTopLevelPredicate(sqmJoin.getJoinPredicate()));
currentlyProcessingJoin = oldJoin;
}
if (transitive) {
consumeExplicitJoins(sqmJoin, joinedTableGroup);
}
return joinedTableGroup;
}
use of org.hibernate.sql.ast.tree.from.PluralTableGroup in project hibernate-orm by hibernate.
the class BaseSqmToSqlAstConverter method consumePluralPartJoin.
private TableGroup consumePluralPartJoin(SqmPluralPartJoin<?, ?> sqmJoin, TableGroup lhsTableGroup, boolean transitive) {
final PluralTableGroup pluralTableGroup = (PluralTableGroup) lhsTableGroup;
final TableGroup tableGroup = getPluralPartTableGroup(pluralTableGroup, sqmJoin.getReferencedPathSource());
getFromClauseIndex().register(sqmJoin, tableGroup);
assert sqmJoin.getJoinPredicate() == null;
if (transitive) {
consumeExplicitJoins(sqmJoin, tableGroup);
}
return tableGroup;
}
use of org.hibernate.sql.ast.tree.from.PluralTableGroup in project hibernate-orm by hibernate.
the class BaseSqmToSqlAstConverter method consumeFromClauseCorrelatedRoot.
protected void consumeFromClauseCorrelatedRoot(SqmRoot<?> sqmRoot) {
log.tracef("Resolving SqmRoot [%s] to TableGroup", sqmRoot);
final FromClauseIndex fromClauseIndex = getFromClauseIndex();
if (fromClauseIndex.isResolved(sqmRoot)) {
log.tracef("Already resolved SqmRoot [%s] to TableGroup", sqmRoot);
}
final QuerySpec currentQuerySpec = currentQuerySpec();
final TableGroup tableGroup;
if (!sqmRoot.isCorrelated()) {
return;
}
final SessionFactoryImplementor sessionFactory = creationContext.getSessionFactory();
if (sqmRoot.containsOnlyInnerJoins()) {
// If we have just inner joins against a correlated root, we can render the joins as references
final SqmFrom<?, ?> from;
// It will always contain just a single correlated join though, which is what is actually correlated
if (sqmRoot instanceof SqmCorrelatedRootJoin<?>) {
assert sqmRoot.getSqmJoins().size() == 1;
assert sqmRoot.getSqmJoins().get(0).isCorrelated();
from = sqmRoot.getSqmJoins().get(0);
} else {
from = sqmRoot;
}
final TableGroup parentTableGroup = fromClauseIndex.findTableGroupOnParents(from.getCorrelationParent().getNavigablePath());
final SqlAliasBase sqlAliasBase = sqlAliasBaseManager.createSqlAliasBase(parentTableGroup.getGroupAlias());
if (parentTableGroup instanceof PluralTableGroup) {
final PluralTableGroup pluralTableGroup = (PluralTableGroup) parentTableGroup;
final CorrelatedPluralTableGroup correlatedPluralTableGroup = new CorrelatedPluralTableGroup(parentTableGroup, sqlAliasBase, currentQuerySpec, predicate -> additionalRestrictions = SqlAstTreeHelper.combinePredicates(additionalRestrictions, predicate), sessionFactory);
final TableGroup elementTableGroup = pluralTableGroup.getElementTableGroup();
if (elementTableGroup != null) {
final TableGroup correlatedElementTableGroup = new CorrelatedTableGroup(elementTableGroup, sqlAliasBase, currentQuerySpec, predicate -> additionalRestrictions = SqlAstTreeHelper.combinePredicates(additionalRestrictions, predicate), sessionFactory);
final TableGroupJoin tableGroupJoin = new TableGroupJoin(elementTableGroup.getNavigablePath(), SqlAstJoinType.INNER, correlatedElementTableGroup);
correlatedPluralTableGroup.registerElementTableGroup(tableGroupJoin);
}
final TableGroup indexTableGroup = pluralTableGroup.getIndexTableGroup();
if (indexTableGroup != null) {
final TableGroup correlatedIndexTableGroup = new CorrelatedTableGroup(indexTableGroup, sqlAliasBase, currentQuerySpec, predicate -> additionalRestrictions = SqlAstTreeHelper.combinePredicates(additionalRestrictions, predicate), sessionFactory);
final TableGroupJoin tableGroupJoin = new TableGroupJoin(indexTableGroup.getNavigablePath(), SqlAstJoinType.INNER, correlatedIndexTableGroup);
correlatedPluralTableGroup.registerIndexTableGroup(tableGroupJoin);
}
tableGroup = correlatedPluralTableGroup;
} else {
tableGroup = new CorrelatedTableGroup(parentTableGroup, sqlAliasBase, currentQuerySpec, predicate -> additionalRestrictions = SqlAstTreeHelper.combinePredicates(additionalRestrictions, predicate), sessionFactory);
}
fromClauseIndex.register(from, tableGroup);
registerPluralTableGroupParts(tableGroup);
log.tracef("Resolved SqmRoot [%s] to correlated TableGroup [%s]", sqmRoot, tableGroup);
consumeExplicitJoins(from, tableGroup);
return;
} else {
final EntityPersister entityDescriptor = resolveEntityPersister(sqmRoot.getReferencedPathSource());
final TableGroup parentTableGroup = fromClauseIndex.findTableGroupOnParents(sqmRoot.getCorrelationParent().getNavigablePath());
// If we have non-inner joins against a correlated root, we must render the root with a correlation predicate
tableGroup = entityDescriptor.createRootTableGroup(true, sqmRoot.getNavigablePath(), sqmRoot.getExplicitAlias(), () -> predicate -> {
}, this, creationContext);
final EntityIdentifierMapping identifierMapping = entityDescriptor.getIdentifierMapping();
final NavigablePath navigablePath = sqmRoot.getNavigablePath().append(identifierMapping.getNavigableRole().getNavigableName());
final int jdbcTypeCount = identifierMapping.getJdbcTypeCount();
if (jdbcTypeCount == 1) {
identifierMapping.forEachSelectable((index, selectable) -> additionalRestrictions = SqlAstTreeHelper.combinePredicates(additionalRestrictions, new ComparisonPredicate(new ColumnReference(parentTableGroup.resolveTableReference(navigablePath, selectable.getContainingTableExpression()), selectable, sessionFactory), ComparisonOperator.EQUAL, new ColumnReference(tableGroup.resolveTableReference(navigablePath, selectable.getContainingTableExpression()), selectable, sessionFactory))));
} else {
final List<Expression> lhs = new ArrayList<>(jdbcTypeCount);
final List<Expression> rhs = new ArrayList<>(jdbcTypeCount);
identifierMapping.forEachSelectable((index, selectable) -> {
lhs.add(new ColumnReference(parentTableGroup.resolveTableReference(navigablePath, selectable.getContainingTableExpression()), selectable, sessionFactory));
rhs.add(new ColumnReference(tableGroup.resolveTableReference(navigablePath, selectable.getContainingTableExpression()), selectable, sessionFactory));
});
additionalRestrictions = SqlAstTreeHelper.combinePredicates(additionalRestrictions, new ComparisonPredicate(new SqlTuple(lhs, identifierMapping), ComparisonOperator.EQUAL, new SqlTuple(rhs, identifierMapping)));
}
}
log.tracef("Resolved SqmRoot [%s] to new TableGroup [%s]", sqmRoot, tableGroup);
fromClauseIndex.register(sqmRoot, tableGroup);
currentQuerySpec.getFromClause().addRoot(tableGroup);
consumeJoins(sqmRoot, fromClauseIndex, tableGroup);
}
Aggregations