use of org.hibernate.query.sqm.tree.domain.SqmTreatedPath in project hibernate-orm by hibernate.
the class BaseSqmToSqlAstConverter method prepareForSelection.
private void prepareForSelection(SqmPath<?> selectionPath) {
final SqmPath<?> path;
// through a cardinality preserving mechanism in visitIndexAggregateFunction/visitElementAggregateFunction
if (selectionPath instanceof AbstractSqmSpecificPluralPartPath<?>) {
path = selectionPath.getLhs().getLhs();
} else {
path = selectionPath;
}
final FromClauseIndex fromClauseIndex = getFromClauseIndex();
final TableGroup tableGroup = fromClauseIndex.findTableGroup(path.getNavigablePath());
if (tableGroup == null) {
prepareReusablePath(path, () -> null);
final NavigablePath navigablePath;
if (CollectionPart.Nature.fromNameExact(path.getNavigablePath().getUnaliasedLocalName()) != null) {
navigablePath = path.getLhs().getLhs().getNavigablePath();
} else if (path instanceof SqmTreatedRoot<?, ?>) {
navigablePath = ((SqmTreatedRoot<?, ?>) path).getWrappedPath().getNavigablePath();
} else {
navigablePath = path.getLhs().getNavigablePath();
}
final TableGroup createdTableGroup = createTableGroup(fromClauseIndex.getTableGroup(navigablePath), path);
if (createdTableGroup != null) {
if (path instanceof SqmTreatedPath<?, ?>) {
fromClauseIndex.register(path, createdTableGroup);
}
if (path instanceof SqmFrom<?, ?>) {
registerTreatUsage((SqmFrom<?, ?>) path, createdTableGroup);
}
}
} else if (path instanceof SqmFrom<?, ?>) {
registerTreatUsage((SqmFrom<?, ?>) path, tableGroup);
}
}
use of org.hibernate.query.sqm.tree.domain.SqmTreatedPath in project hibernate-orm by hibernate.
the class BaseSqmToSqlAstConverter method withTreatRestriction.
private Expression withTreatRestriction(Expression expression, SqmPath<?> path) {
final SqmPath<?> lhs;
if (path instanceof SqmTreatedPath<?, ?>) {
lhs = path;
} else {
lhs = path.getLhs();
}
if (lhs instanceof SqmTreatedPath<?, ?>) {
final SqmTreatedPath<?, ?> treatedPath = (SqmTreatedPath<?, ?>) lhs;
final Class<?> treatTargetJavaType = treatedPath.getTreatTarget().getJavaType();
final Class<?> originalJavaType = treatedPath.getWrappedPath().getJavaType();
if (treatTargetJavaType.isAssignableFrom(originalJavaType)) {
// Treating a node to a super type can be ignored
return expression;
}
if (!(expression.getExpressionType() instanceof BasicValuedMapping)) {
// A case wrapper for non-basic paths is not possible,
// because a case expression must return a scalar value,
// so we instead add the type restriction predicate as conjunct
final MappingMetamodel domainModel = creationContext.getSessionFactory().getRuntimeMetamodels().getMappingMetamodel();
final EntityPersister entityDescriptor = domainModel.findEntityDescriptor(treatedPath.getTreatTarget().getHibernateEntityName());
conjunctTreatUsages.computeIfAbsent(treatedPath.getWrappedPath(), p -> new HashSet<>(1)).addAll(entityDescriptor.getSubclassEntityNames());
return expression;
}
// Note: If the columns that are accessed are not shared with other entities, we could avoid this wrapping
return createCaseExpression(treatedPath.getWrappedPath(), treatedPath.getTreatTarget(), expression);
}
return expression;
}
use of org.hibernate.query.sqm.tree.domain.SqmTreatedPath in project hibernate-orm by hibernate.
the class BaseSqmToSqlAstConverter method createTableGroup.
private TableGroup createTableGroup(TableGroup parentTableGroup, SqmPath<?> joinedPath) {
final TableGroup actualParentTableGroup = findActualTableGroup(parentTableGroup, joinedPath);
final SqmPath<?> lhsPath = joinedPath.getLhs();
final FromClauseIndex fromClauseIndex = getFromClauseIndex();
final ModelPart subPart = actualParentTableGroup.getModelPart().findSubPart(joinedPath.getReferencedPathSource().getPathName(), lhsPath instanceof SqmTreatedPath ? resolveEntityPersister(((SqmTreatedPath<?, ?>) lhsPath).getTreatTarget()) : null);
final TableGroup tableGroup;
if (subPart instanceof TableGroupJoinProducer) {
final TableGroupJoinProducer joinProducer = (TableGroupJoinProducer) subPart;
if (fromClauseIndex.findTableGroup(actualParentTableGroup.getNavigablePath()) == null) {
final QuerySpec querySpec = currentQuerySpec();
// The parent table group is on a parent query, so we need a root table group
tableGroup = joinProducer.createRootTableGroupJoin(joinedPath.getNavigablePath(), actualParentTableGroup, null, null, false, querySpec::applyPredicate, this);
// Force initialization of a possible lazy table group
tableGroup.getPrimaryTableReference();
querySpec.getFromClause().addRoot(tableGroup);
} else {
// Check if we can reuse a table group join of the parent
final TableGroup compatibleTableGroup = findCompatibleJoinedGroup(actualParentTableGroup, joinProducer, SqlAstJoinType.INNER);
if (compatibleTableGroup == null) {
final TableGroupJoin tableGroupJoin = joinProducer.createTableGroupJoin(joinedPath.getNavigablePath(), actualParentTableGroup, null, null, false, false, this);
// Implicit joins in the ON clause of attribute joins need to be added as nested table group joins
// We don't have to do that for entity joins etc. as these do not have an inherent dependency on the lhs.
// We can just add the implicit join before the currently processing join
// See consumeEntityJoin for details
final boolean nested = currentClauseStack.getCurrent() == Clause.FROM && currentlyProcessingJoin instanceof SqmAttributeJoin<?, ?>;
if (nested) {
actualParentTableGroup.addNestedTableGroupJoin(tableGroupJoin);
} else {
actualParentTableGroup.addTableGroupJoin(tableGroupJoin);
}
tableGroup = tableGroupJoin.getJoinedGroup();
} else {
tableGroup = compatibleTableGroup;
}
}
fromClauseIndex.register(joinedPath, tableGroup);
registerPluralTableGroupParts(tableGroup);
} else {
tableGroup = null;
}
return tableGroup;
}
use of org.hibernate.query.sqm.tree.domain.SqmTreatedPath in project hibernate-orm by hibernate.
the class BaseSqmToSqlAstConverter method prepareReusablePath.
private TableGroup prepareReusablePath(FromClauseIndex fromClauseIndex, JpaPath<?> sqmPath, Consumer<TableGroup> implicitJoinChecker) {
final JpaPath<?> parentPath;
if (sqmPath instanceof SqmTreatedPath<?, ?>) {
parentPath = ((SqmTreatedPath<?, ?>) sqmPath).getWrappedPath();
} else {
parentPath = sqmPath.getParentPath();
}
if (parentPath == null) {
return null;
}
final TableGroup tableGroup = fromClauseIndex.findTableGroup(parentPath.getNavigablePath());
if (tableGroup == null) {
final TableGroup parentTableGroup = prepareReusablePath(fromClauseIndex, parentPath, implicitJoinChecker);
if (parentTableGroup == null) {
final TableGroup parent = fromClauseIndex.findTableGroupOnParents(parentPath.getNavigablePath());
if (parent != null) {
throw new SqlTreeCreationException("Found un-correlated path usage in sub query - " + parentPath);
}
throw new SqlTreeCreationException("Could not locate TableGroup - " + parentPath.getNavigablePath());
}
if (parentPath instanceof SqmTreatedPath<?, ?>) {
fromClauseIndex.register((SqmPath<?>) parentPath, parentTableGroup);
return parentTableGroup;
}
final TableGroup newTableGroup = createTableGroup(parentTableGroup, (SqmPath<?>) parentPath);
if (newTableGroup != null) {
implicitJoinChecker.accept(newTableGroup);
if (sqmPath instanceof SqmFrom<?, ?>) {
registerTreatUsage((SqmFrom<?, ?>) sqmPath, newTableGroup);
}
}
return newTableGroup;
} else if (sqmPath instanceof SqmTreatedPath<?, ?>) {
fromClauseIndex.register((SqmPath<?>) sqmPath, tableGroup);
if (sqmPath instanceof SqmFrom<?, ?>) {
registerTreatUsage((SqmFrom<?, ?>) sqmPath, tableGroup);
}
} else if (parentPath instanceof SqmFrom<?, ?>) {
registerTreatUsage((SqmFrom<?, ?>) parentPath, tableGroup);
}
return tableGroup;
}
Aggregations