use of org.hibernate.query.sqm.tree.from.SqmFromClause in project hibernate-orm by hibernate.
the class FromClauseTests method simpleJoinAssertions.
private void simpleJoinAssertions(SqmSelectStatement<?> selectStatement, SqmJoinType joinType, String rootAlias, String joinAlias) {
final SqmFromClause fromClause = selectStatement.getQuerySpec().getFromClause();
assertThat(fromClause, notNullValue());
assertThat(fromClause.getRoots(), hasSize(1));
final SqmRoot<?> sqmRoot = fromClause.getRoots().get(0);
assertThat(sqmRoot, notNullValue());
assertThat(sqmRoot.getExplicitAlias(), is(rootAlias));
assertThat(sqmRoot.getJoins(), hasSize(1));
assertThat(sqmRoot.getSqmJoins().get(0).getExplicitAlias(), is(joinAlias));
assertThat(sqmRoot.getSqmJoins().get(0).getSqmJoinType(), is(joinType));
}
use of org.hibernate.query.sqm.tree.from.SqmFromClause in project hibernate-orm by hibernate.
the class SemanticQueryBuilder method visitFromClause.
@Override
public SqmFromClause visitFromClause(HqlParser.FromClauseContext parserFromClause) {
final SqmFromClause fromClause;
if (parserFromClause == null) {
fromClause = new SqmFromClause();
currentQuerySpec().setFromClause(fromClause);
} else {
final int size = parserFromClause.getChildCount();
// Shift 1 bit instead of division by 2
final int estimatedSize = size >> 1;
fromClause = new SqmFromClause(estimatedSize);
currentQuerySpec().setFromClause(fromClause);
for (int i = 0; i < size; i++) {
final ParseTree parseTree = parserFromClause.getChild(i);
if (parseTree instanceof HqlParser.EntityWithJoinsContext) {
visitEntityWithJoins((HqlParser.EntityWithJoinsContext) parseTree);
}
}
}
return fromClause;
}
use of org.hibernate.query.sqm.tree.from.SqmFromClause in project hibernate-orm by hibernate.
the class SemanticQueryBuilder method visitEntityWithJoins.
@Override
public SqmRoot<?> visitEntityWithJoins(HqlParser.EntityWithJoinsContext parserSpace) {
final SqmRoot<?> sqmRoot = visitRootEntity((HqlParser.RootEntityContext) parserSpace.getChild(0));
final SqmFromClause fromClause = currentQuerySpec().getFromClause();
// Correlations are implicitly added to the from clause
if (!(sqmRoot instanceof SqmCorrelation<?, ?>)) {
fromClause.addRoot(sqmRoot);
}
final int size = parserSpace.getChildCount();
for (int i = 1; i < size; i++) {
final ParseTree parseTree = parserSpace.getChild(i);
if (parseTree instanceof HqlParser.CrossJoinContext) {
consumeCrossJoin((HqlParser.CrossJoinContext) parseTree, sqmRoot);
} else if (parseTree instanceof HqlParser.JoinContext) {
consumeJoin((HqlParser.JoinContext) parseTree, sqmRoot);
} else if (parseTree instanceof HqlParser.JpaCollectionJoinContext) {
consumeJpaCollectionJoin((HqlParser.JpaCollectionJoinContext) parseTree, sqmRoot);
}
}
return sqmRoot;
}
use of org.hibernate.query.sqm.tree.from.SqmFromClause 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.from.SqmFromClause 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