use of org.hibernate.query.sqm.tree.from.SqmRoot in project hibernate-orm by hibernate.
the class FromClauseTests method testFromElementReferenceInSelect.
@Test
public void testFromElementReferenceInSelect() {
final String query = "select p from Person p";
SqmSelectStatement<?> selectStatement = interpretSelect(query);
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(selectStatement.getQuerySpec().getSelectClause().getSelections(), hasSize(1));
final SqmSelection<?> sqmSelection = selectStatement.getQuerySpec().getSelectClause().getSelections().get(0);
assertThat(sqmSelection.getSelectableNode(), instanceOf(SqmRoot.class));
}
use of org.hibernate.query.sqm.tree.from.SqmRoot in project hibernate-orm by hibernate.
the class AliasCollisionTest method testSameIdentificationVariablesInSubquery.
@Test
public void testSameIdentificationVariablesInSubquery() {
final String query = "select a from SimpleEntity a where a.someString in (select a.someString from SimpleEntity a where a.someInteger = 5)";
final SqmSelectStatement<?> sqm = interpretSelect(query);
final SqmQuerySpec<?> querySpec = sqm.getQuerySpec();
final List<SqmSelection<?>> selections = querySpec.getSelectClause().getSelections();
assertThat(selections, hasSize(1));
assertThat(selections.get(0).getAlias(), nullValue());
final List<SqmRoot<?>> roots = querySpec.getFromClause().getRoots();
assertThat(roots, hasSize(1));
assertThat(roots.get(0).getJoins(), isEmpty());
assertThat(roots.get(0).getExplicitAlias(), is("a"));
assertThat(querySpec.getWhereClause().getPredicate(), instanceOf(SqmInSubQueryPredicate.class));
final SqmInSubQueryPredicate predicate = (SqmInSubQueryPredicate) querySpec.getWhereClause().getPredicate();
final SqmRoot<?> subQueryRoot = predicate.getSubQueryExpression().getQuerySpec().getFromClause().getRoots().get(0);
assertThat(subQueryRoot.getExplicitAlias(), is("a"));
}
use of org.hibernate.query.sqm.tree.from.SqmRoot in project hibernate-orm by hibernate.
the class AliasCollisionTest method testSubqueryUsingIdentificationVariableDefinedInRootQuery.
@Test
public void testSubqueryUsingIdentificationVariableDefinedInRootQuery() {
final String query = "select a from SimpleEntity a where a.someString in " + "( select b.someString from SimpleEntity b where a.someLong = b.someLong )";
final SqmSelectStatement<?> sqm = interpretSelect(query);
final SqmQuerySpec<?> querySpec = sqm.getQuerySpec();
final List<SqmSelection<?>> selections = querySpec.getSelectClause().getSelections();
assertThat(selections, hasSize(1));
assertThat(selections.get(0).getAlias(), nullValue());
final List<SqmRoot<?>> roots = querySpec.getFromClause().getRoots();
assertThat(roots, hasSize(1));
assertThat(roots.get(0).getJoins(), isEmpty());
assertThat(roots.get(0).getExplicitAlias(), is("a"));
assertThat(querySpec.getWhereClause().getPredicate(), instanceOf(SqmInSubQueryPredicate.class));
final SqmInSubQueryPredicate predicate = (SqmInSubQueryPredicate) querySpec.getWhereClause().getPredicate();
final SqmQuerySpec subQuerySpec = predicate.getSubQueryExpression().getQuerySpec();
assertThat(subQuerySpec.getFromClause().getRoots().get(0).getExplicitAlias(), is("b"));
final SqmComparisonPredicate correlation = (SqmComparisonPredicate) subQuerySpec.getWhereClause().getPredicate();
final SqmSimplePath leftHandExpression = (SqmSimplePath) correlation.getLeftHandExpression();
assertThat(leftHandExpression.getLhs().getExplicitAlias(), is("a"));
final SqmSimplePath rightHandExpression = (SqmSimplePath) correlation.getRightHandExpression();
assertThat(rightHandExpression.getLhs().getExplicitAlias(), is("b"));
}
use of org.hibernate.query.sqm.tree.from.SqmRoot in project hibernate-orm by hibernate.
the class BaseSqmToSqlAstConverter method visitTableGroup.
private Expression visitTableGroup(TableGroup tableGroup, SqmFrom<?, ?> path) {
final ModelPartContainer modelPart;
final MappingModelExpressible<?> inferredValueMapping = getInferredValueMapping();
// For plain SqmFrom node uses, prefer the mapping type from the context if possible
if (!(inferredValueMapping instanceof ModelPartContainer)) {
modelPart = tableGroup.getModelPart();
} else {
modelPart = (ModelPartContainer) inferredValueMapping;
}
final ModelPart resultModelPart;
final ModelPart interpretationModelPart;
final TableGroup parentGroupToUse;
if (modelPart instanceof ToOneAttributeMapping) {
final ToOneAttributeMapping toOneAttributeMapping = (ToOneAttributeMapping) modelPart;
final ModelPart targetPart = toOneAttributeMapping.getForeignKeyDescriptor().getPart(toOneAttributeMapping.getSideNature().inverse());
if (tableGroup.getModelPart().getPartMappingType() == modelPart.getPartMappingType()) {
resultModelPart = targetPart;
} else {
// If the table group is for a different mapping type i.e. an inheritance subtype,
// lookup the target part on that mapping type
resultModelPart = tableGroup.getModelPart().findSubPart(targetPart.getPartName(), null);
}
interpretationModelPart = modelPart;
parentGroupToUse = null;
} else if (modelPart instanceof PluralAttributeMapping) {
final PluralAttributeMapping pluralAttributeMapping = (PluralAttributeMapping) modelPart;
final CollectionPart elementDescriptor = pluralAttributeMapping.getElementDescriptor();
if (elementDescriptor instanceof EntityCollectionPart) {
// Usually, we need to resolve to the PK for visitTableGroup
final EntityCollectionPart collectionPart = (EntityCollectionPart) elementDescriptor;
final ModelPart collectionTargetPart = collectionPart.getForeignKeyDescriptor().getPart(collectionPart.getSideNature().inverse());
final EntityIdentifierMapping identifierMapping = collectionPart.getEntityMappingType().getIdentifierMapping();
// If the FK points to the PK, we can use the FK part though, if this is not a root
if (collectionTargetPart == identifierMapping && !(path instanceof SqmRoot<?>)) {
resultModelPart = collectionPart.getForeignKeyDescriptor().getPart(collectionPart.getSideNature());
} else {
resultModelPart = identifierMapping;
}
} else {
resultModelPart = elementDescriptor;
}
interpretationModelPart = elementDescriptor;
parentGroupToUse = null;
} else if (modelPart instanceof EntityCollectionPart) {
// Usually, we need to resolve to the PK for visitTableGroup
final EntityCollectionPart collectionPart = (EntityCollectionPart) modelPart;
final ModelPart collectionTargetPart = collectionPart.getForeignKeyDescriptor().getPart(collectionPart.getSideNature().inverse());
final EntityIdentifierMapping identifierMapping = collectionPart.getEntityMappingType().getIdentifierMapping();
// If the FK points to the PK, we can use the FK part though, if this is not a root
if (collectionTargetPart == identifierMapping && !(path instanceof SqmRoot<?>)) {
resultModelPart = collectionPart.getForeignKeyDescriptor().getPart(collectionPart.getSideNature());
} else {
resultModelPart = identifierMapping;
}
interpretationModelPart = modelPart;
parentGroupToUse = findTableGroup(tableGroup.getNavigablePath().getParent());
} else if (modelPart instanceof EntityMappingType) {
resultModelPart = ((EntityMappingType) modelPart).getIdentifierMapping();
interpretationModelPart = modelPart;
// todo: I think this will always be null anyways because EntityMappingType will only be the model part
// of a TableGroup if that is a root TableGroup, so check if we can just switch to null
parentGroupToUse = findTableGroup(tableGroup.getNavigablePath().getParent());
} else {
resultModelPart = modelPart;
interpretationModelPart = modelPart;
parentGroupToUse = null;
}
final NavigablePath navigablePath;
if (interpretationModelPart == modelPart) {
navigablePath = tableGroup.getNavigablePath();
} else {
navigablePath = tableGroup.getNavigablePath().append(interpretationModelPart.getPartName());
}
final Expression result;
if (interpretationModelPart instanceof EntityValuedModelPart) {
final boolean expandToAllColumns;
if (currentClauseStack.getCurrent() == Clause.GROUP) {
// When the table group is known to be fetched i.e. a fetch join
// but also when the from clause is part of the select clause
// we need to expand to all columns, as we also expand this to all columns in the select clause
expandToAllColumns = tableGroup.isFetched() || selectClauseContains(path);
} else {
expandToAllColumns = false;
}
final EntityValuedModelPart mapping = (EntityValuedModelPart) interpretationModelPart;
EntityMappingType mappingType;
if (path instanceof SqmTreatedPath) {
mappingType = creationContext.getSessionFactory().getRuntimeMetamodels().getMappingMetamodel().findEntityDescriptor(((SqmTreatedPath<?, ?>) path).getTreatTarget().getHibernateEntityName());
} else {
mappingType = mapping.getEntityMappingType();
}
result = EntityValuedPathInterpretation.from(navigablePath, parentGroupToUse == null ? tableGroup : parentGroupToUse, expandToAllColumns ? null : resultModelPart, (EntityValuedModelPart) interpretationModelPart, mappingType, this);
} else if (interpretationModelPart instanceof EmbeddableValuedModelPart) {
final EmbeddableValuedModelPart mapping = (EmbeddableValuedModelPart) resultModelPart;
result = new EmbeddableValuedPathInterpretation<>(mapping.toSqlExpression(tableGroup, currentClauseStack.getCurrent(), this, getSqlAstCreationState()), navigablePath, (EmbeddableValuedModelPart) interpretationModelPart, tableGroup);
} else {
assert interpretationModelPart instanceof BasicValuedModelPart;
final BasicValuedModelPart mapping = (BasicValuedModelPart) resultModelPart;
final TableReference tableReference = tableGroup.resolveTableReference(navigablePath.append(resultModelPart.getPartName()), mapping.getContainingTableExpression());
final Expression expression = getSqlExpressionResolver().resolveSqlExpression(SqlExpressionResolver.createColumnReferenceKey(tableReference, mapping.getSelectionExpression()), sacs -> new ColumnReference(tableReference.getIdentificationVariable(), mapping, getCreationContext().getSessionFactory()));
final ColumnReference columnReference;
if (expression instanceof ColumnReference) {
columnReference = (ColumnReference) expression;
} else if (expression instanceof SqlSelectionExpression) {
final Expression selectedExpression = ((SqlSelectionExpression) expression).getSelection().getExpression();
assert selectedExpression instanceof ColumnReference;
columnReference = (ColumnReference) selectedExpression;
} else {
throw new UnsupportedOperationException("Unsupported basic-valued path expression : " + expression);
}
result = new BasicValuedPathInterpretation<>(columnReference, navigablePath, (BasicValuedModelPart) interpretationModelPart, tableGroup);
}
return withTreatRestriction(result, path);
}
use of org.hibernate.query.sqm.tree.from.SqmRoot in project hibernate-orm by hibernate.
the class SemanticQueryBuilder method visitRootEntity.
@Override
@SuppressWarnings({ "rawtypes", "unchecked" })
public SqmRoot<?> visitRootEntity(HqlParser.RootEntityContext ctx) {
final HqlParser.EntityNameContext entityNameContext = (HqlParser.EntityNameContext) ctx.getChild(0);
final List<ParseTree> entityNameParseTreeChildren = entityNameContext.children;
final String name = getEntityName(entityNameContext);
log.debugf("Handling root path - %s", name);
final EntityDomainType entityDescriptor = getCreationContext().getJpaMetamodel().getHqlEntityReference(name);
final HqlParser.VariableContext identificationVariableDefContext;
if (ctx.getChildCount() > 1) {
identificationVariableDefContext = (HqlParser.VariableContext) ctx.getChild(1);
} else {
identificationVariableDefContext = null;
}
final String alias = applyJpaCompliance(visitVariable(identificationVariableDefContext));
final SqmCreationProcessingState processingState = processingStateStack.getCurrent();
final SqmPathRegistry pathRegistry = processingState.getPathRegistry();
if (entityDescriptor == null) {
final int size = entityNameParseTreeChildren.size();
// Handle the use of a correlation path in subqueries
if (processingStateStack.depth() > 1 && size > 2) {
final String parentAlias = entityNameParseTreeChildren.get(0).getText();
final AbstractSqmFrom<?, ?> correlation = processingState.getPathRegistry().findFromByAlias(parentAlias, true);
if (correlation instanceof SqmCorrelation<?, ?>) {
final DotIdentifierConsumer dotIdentifierConsumer = new QualifiedJoinPathConsumer(correlation, SqmJoinType.INNER, false, alias, this);
final int lastIdx = size - 1;
for (int i = 2; i != lastIdx; i += 2) {
dotIdentifierConsumer.consumeIdentifier(entityNameParseTreeChildren.get(i).getText(), false, false);
}
dotIdentifierConsumer.consumeIdentifier(entityNameParseTreeChildren.get(lastIdx).getText(), false, true);
return ((SqmCorrelation<?, ?>) correlation).getCorrelatedRoot();
}
throw new SemanticException("Could not resolve entity or correlation path '" + name + "'");
}
throw new UnknownEntityException("Could not resolve root entity '" + name + "'", name);
}
checkFQNEntityNameJpaComplianceViolationIfNeeded(name, entityDescriptor);
if (entityDescriptor instanceof SqmPolymorphicRootDescriptor) {
if (getCreationOptions().useStrictJpaCompliance()) {
throw new StrictJpaComplianceViolation("Encountered unmapped polymorphic reference [" + entityDescriptor.getHibernateEntityName() + "], but strict JPQL compliance was requested", StrictJpaComplianceViolation.Type.UNMAPPED_POLYMORPHISM);
}
if (processingStateStack.depth() > 1) {
throw new SemanticException("Illegal implicit-polymorphic domain path in subquery '" + entityDescriptor.getName() + "'");
}
}
final SqmRoot<?> sqmRoot = new SqmRoot<>(entityDescriptor, alias, true, creationContext.getNodeBuilder());
pathRegistry.register(sqmRoot);
return sqmRoot;
}
Aggregations