use of org.hibernate.sql.ast.tree.predicate.PredicateCollector 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.predicate.PredicateCollector in project hibernate-orm by hibernate.
the class RestrictedDeleteExecutionDelegate method execute.
@Override
public int execute(DomainQueryExecutionContext executionContext) {
final EntityPersister entityDescriptor = sessionFactory.getRuntimeMetamodels().getMappingMetamodel().getEntityDescriptor(sqmDelete.getTarget().getEntityName());
final String hierarchyRootTableName = ((Joinable) entityDescriptor).getTableName();
final TableGroup deletingTableGroup = converter.getMutatingTableGroup();
final TableReference hierarchyRootTableReference = deletingTableGroup.resolveTableReference(deletingTableGroup.getNavigablePath(), hierarchyRootTableName);
assert hierarchyRootTableReference != null;
final Map<SqmParameter<?>, List<List<JdbcParameter>>> parameterResolutions;
final Map<SqmParameter<?>, MappingModelExpressible<?>> paramTypeResolutions;
if (domainParameterXref.getSqmParameterCount() == 0) {
parameterResolutions = Collections.emptyMap();
paramTypeResolutions = Collections.emptyMap();
} else {
parameterResolutions = new IdentityHashMap<>();
paramTypeResolutions = new LinkedHashMap<>();
}
// Use the converter to interpret the where-clause. We do this for 2 reasons:
// 1) the resolved Predicate is ultimately the base for applying restriction to the deletes
// 2) we also inspect each ColumnReference that is part of the where-clause to see which
// table it comes from. if all of the referenced columns (if any at all) are from the root table
// we can perform all of the deletes without using an id-table
final MutableBoolean needsIdTableWrapper = new MutableBoolean(false);
final Predicate specifiedRestriction = converter.visitWhereClause(sqmDelete.getWhereClause(), columnReference -> {
if (!hierarchyRootTableReference.getIdentificationVariable().equals(columnReference.getQualifier())) {
needsIdTableWrapper.setValue(true);
}
}, (sqmParameter, mappingType, jdbcParameters) -> {
parameterResolutions.computeIfAbsent(sqmParameter, k -> new ArrayList<>(1)).add(jdbcParameters);
paramTypeResolutions.put(sqmParameter, mappingType);
});
final PredicateCollector predicateCollector = new PredicateCollector(specifiedRestriction);
entityDescriptor.applyBaseRestrictions((filterPredicate) -> {
needsIdTableWrapper.setValue(true);
predicateCollector.applyPredicate(filterPredicate);
}, deletingTableGroup, true, executionContext.getSession().getLoadQueryInfluencers().getEnabledFilters(), null, converter);
converter.pruneTableGroupJoins();
// We need an id table if we want to delete from an intermediate table to avoid FK violations
// The intermediate table has a FK to the root table, so we can't delete from the root table first
// Deleting from the intermediate table first also isn't possible,
// because that is the source for deletion in other tables, hence we need an id table
final boolean needsIdTable = needsIdTableWrapper.getValue() || entityDescriptor != entityDescriptor.getRootEntityDescriptor();
final SqmJdbcExecutionContextAdapter executionContextAdapter = SqmJdbcExecutionContextAdapter.omittingLockingAndPaging(executionContext);
if (needsIdTable) {
return executeWithIdTable(predicateCollector.getPredicate(), deletingTableGroup, parameterResolutions, paramTypeResolutions, executionContextAdapter);
} else {
return executeWithoutIdTable(predicateCollector.getPredicate(), deletingTableGroup, parameterResolutions, paramTypeResolutions, converter.getSqlExpressionResolver(), executionContextAdapter);
}
}
use of org.hibernate.sql.ast.tree.predicate.PredicateCollector in project hibernate-orm by hibernate.
the class TableBasedUpdateHandler method resolveDelegate.
private ExecutionDelegate resolveDelegate(DomainQueryExecutionContext executionContext) {
final SessionFactoryImplementor sessionFactory = getSessionFactory();
final MappingMetamodel domainModel = sessionFactory.getRuntimeMetamodels().getMappingMetamodel();
final EntityPersister entityDescriptor = domainModel.getEntityDescriptor(getSqmDeleteOrUpdateStatement().getTarget().getEntityName());
final String rootEntityName = entityDescriptor.getRootEntityName();
final EntityPersister rootEntityDescriptor = domainModel.getEntityDescriptor(rootEntityName);
final String hierarchyRootTableName = ((Joinable) rootEntityDescriptor).getTableName();
final MultiTableSqmMutationConverter converterDelegate = new MultiTableSqmMutationConverter(entityDescriptor, getSqmDeleteOrUpdateStatement(), getSqmDeleteOrUpdateStatement().getTarget(), domainParameterXref, executionContext.getQueryOptions(), executionContext.getSession().getLoadQueryInfluencers(), executionContext.getQueryParameterBindings(), sessionFactory);
final TableGroup updatingTableGroup = converterDelegate.getMutatingTableGroup();
final TableReference hierarchyRootTableReference = updatingTableGroup.resolveTableReference(updatingTableGroup.getNavigablePath(), hierarchyRootTableName);
assert hierarchyRootTableReference != null;
final Map<SqmParameter<?>, List<List<JdbcParameter>>> parameterResolutions;
if (domainParameterXref.getSqmParameterCount() == 0) {
parameterResolutions = Collections.emptyMap();
} else {
parameterResolutions = new IdentityHashMap<>();
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// visit the set-clause using our special converter, collecting
// information about the assignments
final List<Assignment> assignments = new ArrayList<>();
final Map<SqmParameter<?>, MappingModelExpressible<?>> paramTypeResolutions = new LinkedHashMap<>();
converterDelegate.visitSetClause(getSqmDeleteOrUpdateStatement().getSetClause(), assignments::add, (sqmParameter, mappingType, jdbcParameters) -> {
parameterResolutions.computeIfAbsent(sqmParameter, k -> new ArrayList<>(1)).add(jdbcParameters);
paramTypeResolutions.put(sqmParameter, mappingType);
});
converterDelegate.addVersionedAssignment(assignments::add, getSqmDeleteOrUpdateStatement());
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// visit the where-clause using our special converter, collecting information
// about the restrictions
final Predicate providedPredicate;
final SqmWhereClause whereClause = getSqmUpdate().getWhereClause();
if (whereClause == null || whereClause.getPredicate() == null) {
providedPredicate = null;
} else {
providedPredicate = converterDelegate.visitWhereClause(whereClause, columnReference -> {
}, (sqmParameter, mappingType, jdbcParameters) -> {
parameterResolutions.computeIfAbsent(sqmParameter, k -> new ArrayList<>(1)).add(jdbcParameters);
paramTypeResolutions.put(sqmParameter, mappingType);
});
assert providedPredicate != null;
}
final PredicateCollector predicateCollector = new PredicateCollector(providedPredicate);
entityDescriptor.applyBaseRestrictions(predicateCollector::applyPredicate, updatingTableGroup, true, executionContext.getSession().getLoadQueryInfluencers().getEnabledFilters(), null, converterDelegate);
converterDelegate.pruneTableGroupJoins();
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// cross-reference the TableReference by alias. The TableGroup already
// cross-references it by name, bu the ColumnReference only has the alias
final Map<String, TableReference> tableReferenceByAlias = CollectionHelper.mapOfSize(updatingTableGroup.getTableReferenceJoins().size() + 1);
collectTableReference(updatingTableGroup.getPrimaryTableReference(), tableReferenceByAlias::put);
for (int i = 0; i < updatingTableGroup.getTableReferenceJoins().size(); i++) {
collectTableReference(updatingTableGroup.getTableReferenceJoins().get(i), tableReferenceByAlias::put);
}
return new UpdateExecutionDelegate(getSqmUpdate(), converterDelegate, idTable, afterUseAction, sessionUidAccess, domainParameterXref, updatingTableGroup, hierarchyRootTableReference, tableReferenceByAlias, assignments, predicateCollector.getPredicate(), parameterResolutions, paramTypeResolutions, executionContext);
}
Aggregations