use of org.hibernate.query.sqm.tree.select.SqmSelectableNode in project hibernate-orm by hibernate.
the class SemanticQueryBuilder method visitSelectableNode.
private SqmSelectableNode<?> visitSelectableNode(HqlParser.SelectionContext ctx) {
final ParseTree subCtx = ctx.getChild(0).getChild(0);
if (subCtx instanceof HqlParser.ExpressionOrPredicateContext) {
final SqmExpression<?> sqmExpression = (SqmExpression<?>) subCtx.accept(this);
if (sqmExpression instanceof SqmPath) {
final SqmPath<?> sqmPath = (SqmPath<?>) sqmExpression;
if (sqmPath.getReferencedPathSource() instanceof PluralPersistentAttribute) {
// - this is not strictly JPA compliant
if (creationOptions.useStrictJpaCompliance()) {
SqmTreeCreationLogger.LOGGER.debugf("Raw selection of plural attribute not supported by JPA: %s. Use `value(%s)` or `key(%s)` to indicate what part of the collection to select", sqmPath.getAlias(), sqmPath.getAlias(), sqmPath.getAlias());
}
final SqmPath<?> elementPath = sqmPath.resolvePathPart(CollectionPart.Nature.ELEMENT.getName(), true, this);
processingStateStack.getCurrent().getPathRegistry().register(elementPath);
return elementPath;
}
}
return sqmExpression;
}
return (SqmSelectableNode<?>) subCtx.accept(this);
}
use of org.hibernate.query.sqm.tree.select.SqmSelectableNode in project hibernate-orm by hibernate.
the class BaseSqmToSqlAstConverter method determineValueMapping.
private MappingModelExpressible<?> determineValueMapping(SqmExpression<?> sqmExpression, FromClauseIndex fromClauseIndex) {
if (sqmExpression instanceof SqmParameter) {
return determineValueMapping((SqmParameter<?>) sqmExpression);
} else if (sqmExpression instanceof SqmPath) {
log.debugf("Determining mapping-model type for SqmPath : %s ", sqmExpression);
final MappingMetamodel domainModel = creationContext.getSessionFactory().getRuntimeMetamodels().getMappingMetamodel();
return SqmMappingModelHelper.resolveMappingModelExpressible(sqmExpression, domainModel, fromClauseIndex::findTableGroup);
} else // The model type of an enum literal is always inferred
if (sqmExpression instanceof SqmEnumLiteral<?>) {
final MappingModelExpressible<?> mappingModelExpressible = resolveInferredType();
if (mappingModelExpressible != null) {
return mappingModelExpressible;
}
} else if (sqmExpression instanceof SqmSubQuery<?>) {
final SqmSubQuery<?> subQuery = (SqmSubQuery<?>) sqmExpression;
final SqmSelectClause selectClause = subQuery.getQuerySpec().getSelectClause();
if (selectClause.getSelections().size() == 1) {
final SqmSelection<?> subQuerySelection = selectClause.getSelections().get(0);
final SqmSelectableNode<?> selectableNode = subQuerySelection.getSelectableNode();
if (selectableNode instanceof SqmExpression<?>) {
return determineValueMapping((SqmExpression<?>) selectableNode, fromClauseIndex);
}
final SqmExpressible<?> selectionNodeType = subQuerySelection.getNodeType();
if (selectionNodeType != null) {
final MappingMetamodel domainModel = creationContext.getSessionFactory().getRuntimeMetamodels().getMappingMetamodel();
final MappingModelExpressible<?> expressible = domainModel.resolveMappingExpressible(selectionNodeType, this::findTableGroupByPath);
if (expressible != null) {
return expressible;
}
try {
final MappingModelExpressible<?> mappingModelExpressible = resolveInferredType();
if (mappingModelExpressible != null) {
return mappingModelExpressible;
}
} catch (Exception ignore) {
return null;
}
}
}
}
log.debugf("Determining mapping-model type for generalized SqmExpression : %s", sqmExpression);
final SqmExpressible<?> nodeType = sqmExpression.getNodeType();
if (nodeType == null) {
// We can't determine the type of the expression
return null;
}
final MappingMetamodel domainModel = creationContext.getSessionFactory().getRuntimeMetamodels().getMappingMetamodel();
final MappingModelExpressible<?> valueMapping = domainModel.resolveMappingExpressible(nodeType, fromClauseIndex::getTableGroup);
if (valueMapping == null) {
final MappingModelExpressible<?> mappingModelExpressible = resolveInferredType();
if (mappingModelExpressible != null) {
return mappingModelExpressible;
}
}
if (valueMapping == null) {
// For literals it is totally possible that we can't figure out a mapping type
if (sqmExpression instanceof SqmLiteral<?>) {
return null;
}
throw new ConversionException("Could not determine ValueMapping for SqmExpression: " + sqmExpression);
}
return valueMapping;
}
use of org.hibernate.query.sqm.tree.select.SqmSelectableNode in project hibernate-orm by hibernate.
the class BaseSqmToSqlAstConverter method visitSelection.
@Override
public Void visitSelection(SqmSelection<?> sqmSelection) {
final List<Map.Entry<String, DomainResultProducer<?>>> resultProducers;
final SqmSelectableNode<?> selectionNode = sqmSelection.getSelectableNode();
if (selectionNode instanceof SqmJpaCompoundSelection<?>) {
final SqmJpaCompoundSelection<?> selectableNode = (SqmJpaCompoundSelection<?>) selectionNode;
resultProducers = new ArrayList<>(selectableNode.getSelectionItems().size());
for (SqmSelectableNode<?> selectionItem : selectableNode.getSelectionItems()) {
if (selectionItem instanceof SqmPath<?>) {
prepareForSelection((SqmPath<?>) selectionItem);
}
resultProducers.add(new AbstractMap.SimpleEntry<>(selectionItem.getAlias(), (DomainResultProducer<?>) selectionItem.accept(this)));
}
} else {
if (selectionNode instanceof SqmPath<?>) {
prepareForSelection((SqmPath<?>) selectionNode);
}
resultProducers = Collections.singletonList(new AbstractMap.SimpleEntry<>(sqmSelection.getAlias(), (DomainResultProducer<?>) selectionNode.accept(this)));
}
final Stack<SqlAstProcessingState> processingStateStack = getProcessingStateStack();
final boolean needsDomainResults = domainResults != null && currentClauseContributesToTopLevelSelectClause();
final boolean collectDomainResults;
if (processingStateStack.depth() == 1) {
collectDomainResults = needsDomainResults;
} else {
final SqlAstProcessingState current = processingStateStack.getCurrent();
// Since we only want to create domain results for the first/left-most query spec within query groups,
// we have to check if the current query spec is the left-most.
// This is the case when all upper level in-flight query groups are still empty
collectDomainResults = needsDomainResults && processingStateStack.findCurrentFirst(processingState -> {
if (!(processingState instanceof SqlAstQueryPartProcessingState)) {
return Boolean.FALSE;
}
if (processingState == current) {
return null;
}
final QueryPart part = ((SqlAstQueryPartProcessingState) processingState).getInflightQueryPart();
if (part instanceof QueryGroup) {
if (((QueryGroup) part).getQueryParts().isEmpty()) {
return null;
}
}
return Boolean.FALSE;
}) == null;
}
// arguments
if (collectDomainResults) {
resultProducers.forEach(entry -> {
if (!(entry.getValue() instanceof DynamicInstantiation<?>)) {
currentSqlSelectionCollector().next();
}
domainResults.add(entry.getValue().createDomainResult(entry.getKey(), this));
});
} else if (needsDomainResults) {
// We just create domain results for the purpose of creating selections
// This is necessary for top-level query specs within query groups to avoid cycles
resultProducers.forEach(entry -> {
if (!(entry.getValue() instanceof DynamicInstantiation<?>)) {
currentSqlSelectionCollector().next();
}
entry.getValue().createDomainResult(entry.getKey(), this);
});
} else {
resultProducers.forEach(entry -> {
if (!(entry.getValue() instanceof DynamicInstantiation<?>)) {
currentSqlSelectionCollector().next();
}
entry.getValue().applySqlSelections(this);
});
}
return null;
}
Aggregations