use of org.hibernate.sql.ast.spi.SqlAliasBase in project hibernate-orm by hibernate.
the class ToOneAttributeMapping method createRootTableGroupJoin.
@Override
public LazyTableGroup createRootTableGroupJoin(NavigablePath navigablePath, TableGroup lhs, String explicitSourceAlias, SqlAstJoinType requestedJoinType, boolean fetched, Consumer<Predicate> predicateConsumer, SqlAliasBaseGenerator aliasBaseGenerator, SqlExpressionResolver sqlExpressionResolver, FromClauseAccess fromClauseAccess, SqlAstCreationContext creationContext) {
final SqlAliasBase sqlAliasBase = aliasBaseGenerator.createSqlAliasBase(sqlAliasStem);
final SqlAstJoinType joinType;
if (requestedJoinType == null) {
joinType = SqlAstJoinType.INNER;
} else {
joinType = requestedJoinType;
}
final boolean canUseInnerJoin = joinType == SqlAstJoinType.INNER || lhs.canUseInnerJoins() && !isNullable;
TableGroup realParentTableGroup = lhs;
while (realParentTableGroup.getModelPart() instanceof EmbeddableValuedModelPart) {
realParentTableGroup = fromClauseAccess.findTableGroup(realParentTableGroup.getNavigablePath().getParent());
}
final TableGroupProducer tableGroupProducer;
if (realParentTableGroup instanceof CorrelatedTableGroup) {
// If the parent is a correlated table group, we can't refer to columns of the table in the outer query,
// because the context in which a column is used could be an aggregate function.
// Using a parent column in such a case would lead to an error if the parent query lacks a proper group by
tableGroupProducer = entityMappingType;
} else {
tableGroupProducer = this;
}
final LazyTableGroup lazyTableGroup = new LazyTableGroup(canUseInnerJoin, navigablePath, fetched, () -> createTableGroupInternal(canUseInnerJoin, navigablePath, fetched, null, sqlAliasBase, sqlExpressionResolver, creationContext), (np, tableExpression) -> {
if (!canUseParentTableGroup || tableGroupProducer != ToOneAttributeMapping.this) {
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);
}, tableGroupProducer, explicitSourceAlias, sqlAliasBase, creationContext.getSessionFactory(), lhs);
if (predicateConsumer != null) {
final TableReference lhsTableReference = lhs.resolveTableReference(navigablePath, identifyingColumnsTableExpression);
lazyTableGroup.setTableGroupInitializerCallback(tableGroup -> predicateConsumer.accept(foreignKeyDescriptor.generateJoinPredicate(sideNature == ForeignKeyDescriptor.Nature.TARGET ? lhsTableReference : tableGroup.getPrimaryTableReference(), sideNature == ForeignKeyDescriptor.Nature.TARGET ? tableGroup.getPrimaryTableReference() : lhsTableReference, sqlExpressionResolver, creationContext)));
}
if (realParentTableGroup instanceof CorrelatedTableGroup) {
// Force initialization of the underlying table group join to retain cardinality
lazyTableGroup.getPrimaryTableReference();
} else {
initializeIfNeeded(lhs, requestedJoinType, lazyTableGroup);
}
return lazyTableGroup;
}
use of org.hibernate.sql.ast.spi.SqlAliasBase in project hibernate-orm by hibernate.
the class EntityCollectionPart method createRootTableGroupJoin.
@Override
public LazyTableGroup createRootTableGroupJoin(NavigablePath navigablePath, TableGroup lhs, String explicitSourceAlias, SqlAstJoinType requestedJoinType, boolean fetched, Consumer<Predicate> predicateConsumer, SqlAliasBaseGenerator aliasBaseGenerator, SqlExpressionResolver sqlExpressionResolver, FromClauseAccess fromClauseAccess, SqlAstCreationContext creationContext) {
final SqlAstJoinType joinType;
if (requestedJoinType == null) {
joinType = SqlAstJoinType.INNER;
} else {
joinType = requestedJoinType;
}
final SqlAliasBase sqlAliasBase = aliasBaseGenerator.createSqlAliasBase(getSqlAliasStem());
final boolean canUseInnerJoin = joinType == SqlAstJoinType.INNER || lhs.canUseInnerJoins();
final LazyTableGroup lazyTableGroup = new LazyTableGroup(canUseInnerJoin, navigablePath, fetched, () -> createTableGroupInternal(canUseInnerJoin, navigablePath, fetched, null, sqlAliasBase, sqlExpressionResolver, creationContext), (np, tableExpression) -> {
NavigablePath path = np.getParent();
// Fast path
if (path != null && navigablePath.equals(path)) {
return targetKeyPropertyNames.contains(np.getUnaliasedLocalName()) && fkDescriptor.getKeyTable().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()) && fkDescriptor.getKeyTable().equals(tableExpression);
}, this, explicitSourceAlias, sqlAliasBase, creationContext.getSessionFactory(), lhs);
if (predicateConsumer != null) {
final TableReference keySideTableReference = lhs.resolveTableReference(navigablePath, fkDescriptor.getKeyTable());
lazyTableGroup.setTableGroupInitializerCallback(tableGroup -> predicateConsumer.accept(fkDescriptor.generateJoinPredicate(tableGroup.getPrimaryTableReference(), keySideTableReference, sqlExpressionResolver, creationContext)));
}
return lazyTableGroup;
}
use of org.hibernate.sql.ast.spi.SqlAliasBase in project hibernate-orm by hibernate.
the class BaseSqmToSqlAstConverter method visitIsEmptyPredicate.
@Override
public Object visitIsEmptyPredicate(SqmEmptinessPredicate predicate) {
prepareReusablePath(predicate.getPluralPath(), () -> null);
final QuerySpec subQuerySpec = new QuerySpec(false, 1);
final FromClauseAccess parentFromClauseAccess = getFromClauseAccess();
final SqlAstProcessingStateImpl subQueryState = new SqlAstProcessingStateImpl(getCurrentProcessingState(), this, currentClauseStack::getCurrent);
pushProcessingState(subQueryState);
try {
final SqmPluralValuedSimplePath<?> sqmPluralPath = predicate.getPluralPath();
final NavigablePath pluralPathNavPath = sqmPluralPath.getNavigablePath();
final NavigablePath parentNavPath = pluralPathNavPath.getParent();
assert parentNavPath != null;
final TableGroup parentTableGroup = parentFromClauseAccess.getTableGroup(parentNavPath);
final SqlAliasBase sqlAliasBase = sqlAliasBaseManager.createSqlAliasBase(parentTableGroup.getGroupAlias());
final TableGroup tableGroup = new CorrelatedTableGroup(parentTableGroup, sqlAliasBase, subQuerySpec, subQuerySpec::applyPredicate, creationContext.getSessionFactory());
subQueryState.getSqlAstCreationState().getFromClauseAccess().registerTableGroup(parentNavPath, tableGroup);
registerPluralTableGroupParts(tableGroup);
final PluralAttributeMapping pluralAttributeMapping = (PluralAttributeMapping) visitPluralValuedPath(sqmPluralPath).getExpressionType();
// The creation of the table group join against the correlated table group
// has the side effect that the from and where clause of the sub-query are set
tableGroup.addTableGroupJoin(pluralAttributeMapping.createTableGroupJoin(pluralPathNavPath, tableGroup, sqmPluralPath.getExplicitAlias(), SqlAstJoinType.INNER, false, false, sqlAliasBaseManager, subQueryState, this, creationContext));
final ForeignKeyDescriptor collectionKeyDescriptor = pluralAttributeMapping.getKeyDescriptor();
final int jdbcTypeCount = collectionKeyDescriptor.getJdbcTypeCount();
assert jdbcTypeCount > 0;
final JdbcLiteral<Integer> jdbcLiteral = new JdbcLiteral<>(1, basicType(Integer.class));
subQuerySpec.getSelectClause().addSqlSelection(new SqlSelectionImpl(1, 0, jdbcLiteral));
return new ExistsPredicate(subQuerySpec, !predicate.isNegated(), getBooleanType());
} finally {
popProcessingStateStack();
}
}
use of org.hibernate.sql.ast.spi.SqlAliasBase in project hibernate-orm by hibernate.
the class DynamicFetchBuilderLegacy method buildFetch.
@Override
public Fetch buildFetch(FetchParent parent, NavigablePath fetchPath, JdbcValuesMetadata jdbcResultsMetadata, BiFunction<String, String, DynamicFetchBuilderLegacy> legacyFetchResolver, DomainResultCreationState domainResultCreationState) {
final DomainResultCreationStateImpl creationState = ResultsHelper.impl(domainResultCreationState);
final TableGroup ownerTableGroup = creationState.getFromClauseAccess().findByAlias(ownerTableAlias);
final AttributeMapping attributeMapping = parent.getReferencedMappingContainer().findContainingEntityMapping().findDeclaredAttributeMapping(fetchableName);
final TableGroup tableGroup;
if (attributeMapping instanceof TableGroupJoinProducer) {
final SqlAliasBase sqlAliasBase = new SqlAliasBaseConstant(tableAlias);
final TableGroupJoin tableGroupJoin = ((TableGroupJoinProducer) attributeMapping).createTableGroupJoin(fetchPath, ownerTableGroup, tableAlias, SqlAstJoinType.INNER, true, false, s -> sqlAliasBase, creationState.getSqlExpressionResolver(), creationState.getFromClauseAccess(), creationState.getCreationContext());
ownerTableGroup.addTableGroupJoin(tableGroupJoin);
creationState.getFromClauseAccess().registerTableGroup(fetchPath, tableGroup = tableGroupJoin.getJoinedGroup());
} else {
tableGroup = ownerTableGroup;
}
if (columnNames != null) {
final ForeignKeyDescriptor keyDescriptor;
if (attributeMapping instanceof PluralAttributeMapping) {
final PluralAttributeMapping pluralAttributeMapping = (PluralAttributeMapping) attributeMapping;
keyDescriptor = pluralAttributeMapping.getKeyDescriptor();
} else {
// Not sure if this fetch builder can also be used with other attribute mappings
assert attributeMapping instanceof ToOneAttributeMapping;
final ToOneAttributeMapping toOneAttributeMapping = (ToOneAttributeMapping) attributeMapping;
keyDescriptor = toOneAttributeMapping.getForeignKeyDescriptor();
}
if (!columnNames.isEmpty()) {
keyDescriptor.forEachSelectable((selectionIndex, selectableMapping) -> {
resolveSqlSelection(columnNames.get(selectionIndex), createColumnReferenceKey(tableGroup.resolveTableReference(selectableMapping.getContainingTableExpression()), selectableMapping.getSelectionExpression()), selectableMapping.getJdbcMapping(), jdbcResultsMetadata, domainResultCreationState);
});
}
// We process the fetch builder such that it contains a resultBuilderEntity before calling this method in ResultSetMappingProcessor
if (resultBuilderEntity != null) {
return resultBuilderEntity.buildFetch(parent, attributeMapping, jdbcResultsMetadata, creationState);
}
}
try {
final NavigablePath currentRelativePath = creationState.getCurrentRelativePath();
final String prefix;
if (currentRelativePath == null) {
prefix = "";
} else {
prefix = currentRelativePath.getFullPath().replace(ELEMENT_PREFIX, "").replace(INDEX_PREFIX, "") + ".";
}
creationState.pushExplicitFetchMementoResolver(relativePath -> {
if (relativePath.startsWith(prefix)) {
return findFetchBuilder(relativePath.substring(prefix.length()));
}
return null;
});
return parent.generateFetchableFetch(attributeMapping, parent.resolveNavigablePath(attributeMapping), FetchTiming.IMMEDIATE, true, null, domainResultCreationState);
} finally {
creationState.popExplicitFetchMementoResolver();
}
}
use of org.hibernate.sql.ast.spi.SqlAliasBase 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