use of org.hibernate.sql.ast.tree.predicate.ExistsPredicate 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.tree.predicate.ExistsPredicate in project hibernate-orm by hibernate.
the class AbstractSqlAstTranslator method determineLateralEmulationPredicate.
protected Predicate determineLateralEmulationPredicate(TableGroup tableGroup) {
if (tableGroup.getPrimaryTableReference() instanceof QueryPartTableReference) {
final QueryPartTableReference tableReference = (QueryPartTableReference) tableGroup.getPrimaryTableReference();
final List<String> columnNames = tableReference.getColumnNames();
final List<ColumnReference> columnReferences = new ArrayList<>(columnNames.size());
final List<ColumnReference> subColumnReferences = new ArrayList<>(columnNames.size());
final QueryPart queryPart = tableReference.getQueryPart();
for (String columnName : columnNames) {
columnReferences.add(new ColumnReference(tableReference, columnName, false, null, null, null, sessionFactory));
}
// The following optimization only makes sense if the necessary features are supported natively
if ((columnReferences.size() == 1 || supportsRowValueConstructorSyntax()) && supportsDistinctFromPredicate()) {
// ... x(c) on x.c is not distinct from (... fetch first 1 rows only)
if (queryPart.getFetchClauseType() == FetchClauseType.ROWS_ONLY && queryPart.getFetchClauseExpression() instanceof QueryLiteral<?> && Integer.valueOf(1).equals(((QueryLiteral<?>) queryPart.getFetchClauseExpression()).getLiteralValue())) {
return new ComparisonPredicate(new SqlTuple(columnReferences, tableGroup.getModelPart()), ComparisonOperator.NOT_DISTINCT_FROM, queryPart);
}
}
// ... x(c) on exists(select x.c intersect ...)
if (supportsIntersect()) {
final QuerySpec lhsReferencesQuery = new QuerySpec(false);
for (ColumnReference columnReference : columnReferences) {
lhsReferencesQuery.getSelectClause().addSqlSelection(new SqlSelectionImpl(1, 0, columnReference));
}
final List<QueryPart> queryParts = new ArrayList<>(2);
queryParts.add(lhsReferencesQuery);
queryParts.add(queryPart);
return new ExistsPredicate(new QueryGroup(false, SetOperator.INTERSECT, queryParts), false, getBooleanType());
}
// Double nested sub-query rendering if nothing else works
// We try to avoid this as much as possible as it is not very efficient and some DBs don't like it
// when a correlation happens in a sub-query that is not a direct child
// ... x(c) on exists(select 1 from (...) synth_(c) where x.c = synth_.c)
final QueryPartTableGroup subTableGroup = new QueryPartTableGroup(tableGroup.getNavigablePath(), (TableGroupProducer) tableGroup.getModelPart(), queryPart, "synth_", columnNames, false, true, sessionFactory);
for (String columnName : columnNames) {
subColumnReferences.add(new ColumnReference(subTableGroup.getPrimaryTableReference(), columnName, false, null, null, null, sessionFactory));
}
final QuerySpec existsQuery = new QuerySpec(false, 1);
existsQuery.getSelectClause().addSqlSelection(new SqlSelectionImpl(1, 0, new QueryLiteral<>(1, getIntegerType())));
existsQuery.getFromClause().addRoot(subTableGroup);
existsQuery.applyPredicate(new ComparisonPredicate(new SqlTuple(columnReferences, tableGroup.getModelPart()), ComparisonOperator.NOT_DISTINCT_FROM, new SqlTuple(subColumnReferences, tableGroup.getModelPart())));
return new ExistsPredicate(existsQuery, false, getBooleanType());
}
return null;
}
Aggregations