use of org.hibernate.query.sqm.tree.select.SqmSubQuery in project hibernate-orm by hibernate.
the class SemanticQueryBuilder method visitSubquery.
@Override
public SqmSubQuery<?> visitSubquery(HqlParser.SubqueryContext ctx) {
final HqlParser.QueryExpressionContext queryExpressionContext = (HqlParser.QueryExpressionContext) ctx.getChild(0);
final SqmSubQuery<?> subQuery = new SqmSubQuery<>(processingStateStack.getCurrent().getProcessingQuery(), creationContext.getNodeBuilder());
processingStateStack.push(new SqmQuerySpecCreationProcessingStateStandardImpl(processingStateStack.getCurrent(), subQuery, this));
try {
queryExpressionContext.accept(this);
final List<SqmSelection<?>> selections = subQuery.getQuerySpec().getSelectClause().getSelections();
if (selections.size() == 1) {
subQuery.applyInferableType(selections.get(0).getNodeType());
}
return subQuery;
} finally {
processingStateStack.pop();
}
}
use of org.hibernate.query.sqm.tree.select.SqmSubQuery in project hibernate-orm by hibernate.
the class SemanticQueryBuilder method visitAnyFunction.
@Override
public SqmExpression<?> visitAnyFunction(HqlParser.AnyFunctionContext ctx) {
final SqmPredicate filterExpression = getFilterExpression(ctx);
final ParseTree argumentChild = ctx.getChild(2);
if (argumentChild instanceof HqlParser.SubqueryContext) {
final SqmSubQuery<?> subquery = (SqmSubQuery<?>) argumentChild.accept(this);
return new SqmAny<>(subquery, creationContext.getNodeBuilder());
} else if (argumentChild instanceof HqlParser.PredicateContext) {
if (getCreationOptions().useStrictJpaCompliance()) {
throw new StrictJpaComplianceViolation(StrictJpaComplianceViolation.Type.FUNCTION_CALL);
}
final SqmExpression<?> argument = (SqmExpression<?>) argumentChild.accept(this);
return applyOverClause(ctx, getFunctionDescriptor("any").generateAggregateSqmExpression(singletonList(argument), filterExpression, resolveExpressibleTypeBasic(Boolean.class), creationContext.getQueryEngine(), creationContext.getJpaMetamodel().getTypeConfiguration()));
} else {
if (getCreationOptions().useStrictJpaCompliance()) {
throw new StrictJpaComplianceViolation(StrictJpaComplianceViolation.Type.HQL_COLLECTION_FUNCTION);
}
return new SqmAny<>(createCollectionReferenceSubQuery((HqlParser.SimplePathContext) ctx.getChild(3), (TerminalNode) ctx.getChild(1)), creationContext.getNodeBuilder());
}
}
use of org.hibernate.query.sqm.tree.select.SqmSubQuery in project hibernate-orm by hibernate.
the class QualifiedJoinPredicatePathConsumer method createBasePart.
@Override
protected SemanticPathPart createBasePart() {
return new BaseLocalSequencePart() {
@Override
protected void validateAsRoot(SqmFrom<?, ?> pathRoot) {
final SqmRoot<?> root = pathRoot.findRoot();
final SqmRoot<?> joinRoot = sqmJoin.findRoot();
if (root != joinRoot) {
// The root of a path within a join condition doesn't have the same root as the current join we are processing.
// The aim of this check is to prevent uses of different "spaces" i.e. `from A a, B b join b.id = a.id` would be illegal
SqmCreationProcessingState processingState = getCreationState().getCurrentProcessingState();
// First, we need to find out if the current join is part of current processing query
final SqmQuery<?> currentProcessingQuery = processingState.getProcessingQuery();
if (currentProcessingQuery instanceof SqmSelectQuery<?>) {
final SqmQuerySpec<?> querySpec = ((SqmSelectQuery<?>) currentProcessingQuery).getQuerySpec();
final SqmFromClause fromClause = querySpec.getFromClause();
// then the root of the processing path must be a root of one of the parent queries
if (fromClause != null && fromClause.getRoots().contains(joinRoot)) {
// It is allowed to use correlations from the same query
if (!(root instanceof SqmCorrelation<?, ?>) || !fromClause.getRoots().contains(root)) {
validateAsRootOnParentQueryClosure(pathRoot, root, processingState.getParentProcessingState());
}
return;
}
}
// in which case the path root is allowed to occur in the current processing query as root
if (currentProcessingQuery instanceof SqmSubQuery<?>) {
validateAsRootOnParentQueryClosure(pathRoot, root, processingState);
return;
}
throw new SemanticException(String.format(Locale.ROOT, "SqmQualifiedJoin predicate referred to SqmRoot [`%s`] other than the join's root [`%s`]", pathRoot.getNavigablePath().getFullPath(), sqmJoin.getNavigablePath().getFullPath()));
}
super.validateAsRoot(pathRoot);
}
private void validateAsRootOnParentQueryClosure(SqmFrom<?, ?> pathRoot, SqmRoot<?> root, SqmCreationProcessingState processingState) {
while (processingState != null) {
final SqmQuery<?> processingQuery = processingState.getProcessingQuery();
if (processingQuery instanceof SqmSelectQuery<?>) {
final SqmQuerySpec<?> querySpec = ((SqmSelectQuery<?>) processingQuery).getQuerySpec();
final SqmFromClause fromClause = querySpec.getFromClause();
// i.e. `from A a, B b join b.id = a.id` would be illegal
if (fromClause != null && fromClause.getRoots().contains(root)) {
super.validateAsRoot(pathRoot);
return;
}
}
processingState = processingState.getParentProcessingState();
}
throw new SemanticException(String.format(Locale.ROOT, "SqmQualifiedJoin predicate referred to SqmRoot [`%s`] other than the join's root [`%s`]", pathRoot.getNavigablePath().getFullPath(), sqmJoin.getNavigablePath().getFullPath()));
}
};
}
use of org.hibernate.query.sqm.tree.select.SqmSubQuery in project hibernate-orm by hibernate.
the class SemanticQueryBuilder method visitEveryFunction.
@Override
public SqmExpression<?> visitEveryFunction(HqlParser.EveryFunctionContext ctx) {
final SqmPredicate filterExpression = getFilterExpression(ctx);
final ParseTree argumentChild = ctx.getChild(2);
if (argumentChild instanceof HqlParser.SubqueryContext) {
final SqmSubQuery<?> subquery = (SqmSubQuery<?>) argumentChild.accept(this);
return new SqmEvery<>(subquery, creationContext.getNodeBuilder());
} else if (argumentChild instanceof HqlParser.PredicateContext) {
if (getCreationOptions().useStrictJpaCompliance()) {
throw new StrictJpaComplianceViolation(StrictJpaComplianceViolation.Type.FUNCTION_CALL);
}
final SqmExpression<?> argument = (SqmExpression<?>) argumentChild.accept(this);
return applyOverClause(ctx, getFunctionDescriptor("every").generateAggregateSqmExpression(singletonList(argument), filterExpression, resolveExpressibleTypeBasic(Boolean.class), creationContext.getQueryEngine(), creationContext.getJpaMetamodel().getTypeConfiguration()));
} else {
if (getCreationOptions().useStrictJpaCompliance()) {
throw new StrictJpaComplianceViolation(StrictJpaComplianceViolation.Type.HQL_COLLECTION_FUNCTION);
}
return new SqmEvery<>(createCollectionReferenceSubQuery((HqlParser.SimplePathContext) ctx.getChild(3), (TerminalNode) ctx.getChild(1)), creationContext.getNodeBuilder());
}
}
use of org.hibernate.query.sqm.tree.select.SqmSubQuery in project hibernate-orm by hibernate.
the class SemanticQueryBuilder method createCollectionReferenceSubQuery.
private <X> SqmSubQuery<X> createCollectionReferenceSubQuery(HqlParser.SimplePathContext pathCtx, TerminalNode collectionReferenceCtx) {
final SqmPath<?> pluralAttributePath = consumeDomainPath(pathCtx);
final SqmPathSource<?> referencedPathSource = pluralAttributePath.getReferencedPathSource();
if (!(referencedPathSource instanceof PluralPersistentAttribute)) {
throw new PathException("Path is not a plural path '" + pluralAttributePath.getNavigablePath() + "'");
}
final SqmSubQuery<?> subQuery = new SqmSubQuery<>(processingStateStack.getCurrent().getProcessingQuery(), creationContext.getNodeBuilder());
final SqmSelectClause selectClause = new SqmSelectClause(false, 1, creationContext.getNodeBuilder());
final SqmFromClause fromClause = new SqmFromClause(1);
SqmPath<?> lhs = pluralAttributePath.getLhs();
final List<String> implicitJoinPaths = new ArrayList<>();
while (!(lhs instanceof AbstractSqmFrom<?, ?>)) {
implicitJoinPaths.add(lhs.getNavigablePath().getUnaliasedLocalName());
lhs = lhs.getLhs();
}
final AbstractSqmFrom<?, ?> correlationBase = (AbstractSqmFrom<?, ?>) lhs;
final SqmCorrelation<?, ?> correlation = correlationBase.createCorrelation();
SqmFrom<?, ?> joinBase = correlation;
for (int i = implicitJoinPaths.size() - 1; i >= 0; i--) {
joinBase = joinBase.join(implicitJoinPaths.get(i));
}
final SqmAttributeJoin<?, ?> collectionJoin = joinBase.join(pluralAttributePath.getNavigablePath().getUnaliasedLocalName());
fromClause.addRoot(correlation.getCorrelatedRoot());
if (collectionReferenceCtx == null) {
final SqmLiteral<Integer> literal = new SqmLiteral<>(1, creationContext.getNodeBuilder().getIntegerType(), creationContext.getNodeBuilder());
subQuery.applyInferableType(literal.getNodeType());
selectClause.setSelection(literal);
} else {
final String partName;
switch(collectionReferenceCtx.getSymbol().getType()) {
case HqlParser.ELEMENTS:
partName = CollectionPart.Nature.ELEMENT.getName();
break;
case HqlParser.INDICES:
partName = CollectionPart.Nature.INDEX.getName();
break;
default:
throw new ParsingException("Unexpected collection reference : " + collectionReferenceCtx.getText());
}
final SqmPath<?> path = collectionJoin.resolvePathPart(partName, true, this);
subQuery.applyInferableType(path.getNodeType());
selectClause.setSelection(path);
}
final SqmQuerySpec<?> querySpec = subQuery.getQuerySpec();
querySpec.setFromClause(fromClause);
querySpec.setSelectClause(selectClause);
// noinspection unchecked
return (SqmSubQuery<X>) subQuery;
}
Aggregations