use of org.hibernate.query.sqm.tree.select.SqmQueryPart in project hibernate-orm by hibernate.
the class SemanticQueryBuilder method visitSetQueryGroup.
@Override
public SqmQueryGroup<Object> visitSetQueryGroup(HqlParser.SetQueryGroupContext ctx) {
if (creationOptions.useStrictJpaCompliance()) {
throw new StrictJpaComplianceViolation(StrictJpaComplianceViolation.Type.SET_OPERATIONS);
}
final List<ParseTree> children = ctx.children;
// noinspection unchecked
final SqmQueryPart<Object> firstQueryPart = (SqmQueryPart<Object>) children.get(0).accept(this);
SqmQueryGroup<Object> queryGroup;
if (firstQueryPart instanceof SqmQueryGroup<?>) {
queryGroup = (SqmQueryGroup<Object>) firstQueryPart;
} else {
queryGroup = new SqmQueryGroup<>(firstQueryPart);
}
setCurrentQueryPart(queryGroup);
final int size = children.size();
final SqmCreationProcessingState firstProcessingState = processingStateStack.pop();
for (int i = 1; i < size; i += 2) {
final SetOperator operator = visitSetOperator((HqlParser.SetOperatorContext) children.get(i));
final HqlParser.OrderedQueryContext simpleQueryCtx = (HqlParser.OrderedQueryContext) children.get(i + 1);
final List<SqmQueryPart<Object>> queryParts;
if (queryGroup.getSetOperator() == null || queryGroup.getSetOperator() == operator) {
queryGroup.setSetOperator(operator);
queryParts = queryGroup.queryParts();
} else {
queryParts = new ArrayList<>(size - (i >> 1));
queryParts.add(queryGroup);
queryGroup = new SqmQueryGroup<>(creationContext.getNodeBuilder(), operator, queryParts);
setCurrentQueryPart(queryGroup);
}
final SqmQueryPart<Object> queryPart;
try {
processingStateStack.push(new SqmQuerySpecCreationProcessingStateStandardImpl(processingStateStack.getCurrent(), (SqmSelectQuery<?>) firstProcessingState.getProcessingQuery(), this));
final List<ParseTree> subChildren = simpleQueryCtx.children;
if (subChildren.get(0) instanceof HqlParser.QueryContext) {
final SqmQuerySpec<Object> querySpec = new SqmQuerySpec<>(creationContext.getNodeBuilder());
queryParts.add(querySpec);
visitQuerySpecExpression((HqlParser.QuerySpecExpressionContext) simpleQueryCtx);
} else {
try {
final SqmSelectStatement<Object> selectStatement = new SqmSelectStatement<>(creationContext.getNodeBuilder());
processingStateStack.push(new SqmQuerySpecCreationProcessingStateStandardImpl(processingStateStack.getCurrent(), selectStatement, this));
queryPart = visitNestedQueryExpression((HqlParser.NestedQueryExpressionContext) simpleQueryCtx);
queryParts.add(queryPart);
} finally {
processingStateStack.pop();
}
}
} finally {
processingStateStack.pop();
}
}
processingStateStack.push(firstProcessingState);
return queryGroup;
}
use of org.hibernate.query.sqm.tree.select.SqmQueryPart in project hibernate-orm by hibernate.
the class BaseSqmToSqlAstConverter method visitQueryGroup.
@Override
public QueryGroup visitQueryGroup(SqmQueryGroup<?> queryGroup) {
final List<? extends SqmQueryPart<?>> queryParts = queryGroup.getQueryParts();
final int size = queryParts.size();
final List<QueryPart> newQueryParts = new ArrayList<>(size);
final QueryGroup group = new QueryGroup(getProcessingStateStack().isEmpty(), queryGroup.getSetOperator(), newQueryParts);
if (queryGroup.getOrderByClause() != null && queryGroup.getOrderByClause().hasPositionalSortItem()) {
trackSelectionsForGroup = true;
}
final SqlAstQueryPartProcessingStateImpl processingState = new SqlAstQueryPartProcessingStateImpl(group, getCurrentProcessingState(), this, DelegatingSqmAliasedNodeCollector::new, currentClauseStack::getCurrent, deduplicateSelectionItems);
final DelegatingSqmAliasedNodeCollector collector = (DelegatingSqmAliasedNodeCollector) processingState.getSqlExpressionResolver();
final SqmQueryPart<?> sqmQueryPart = currentSqmQueryPart;
currentSqmQueryPart = queryGroup;
pushProcessingState(processingState);
try {
newQueryParts.add(visitQueryPart(queryParts.get(0)));
collector.setSqmAliasedNodeCollector((SqmAliasedNodeCollector) lastPoppedProcessingState.getSqlExpressionResolver());
visitOrderByOffsetAndFetch(queryGroup, group);
trackSelectionsForGroup = false;
for (int i = 1; i < size; i++) {
newQueryParts.add(visitQueryPart(queryParts.get(i)));
}
return group;
} finally {
popProcessingStateStack();
currentSqmQueryPart = sqmQueryPart;
}
}
use of org.hibernate.query.sqm.tree.select.SqmQueryPart in project hibernate-orm by hibernate.
the class BaseSqmToSqlAstConverter method visitQuerySpec.
@Override
public QuerySpec visitQuerySpec(SqmQuerySpec<?> sqmQuerySpec) {
final boolean topLevel = getProcessingStateStack().isEmpty();
final QuerySpec sqlQuerySpec = new QuerySpec(topLevel, sqmQuerySpec.getFromClause().getNumberOfRoots());
final SqmSelectClause selectClause = sqmQuerySpec.getSelectClause();
final Predicate originalAdditionalRestrictions = additionalRestrictions;
additionalRestrictions = null;
final boolean trackAliasedNodePositions;
if (trackSelectionsForGroup) {
trackAliasedNodePositions = true;
} else if (sqmQuerySpec.getOrderByClause() != null && sqmQuerySpec.getOrderByClause().hasPositionalSortItem()) {
trackAliasedNodePositions = true;
} else if (sqmQuerySpec.hasPositionalGroupItem()) {
trackAliasedNodePositions = true;
} else {
// Since JPA Criteria queries can use the same expression object in order or group by items,
// we need to track the positions to be able to replace the expression in the items with alias references
// Also see #resolveGroupOrOrderByExpression for more details
trackAliasedNodePositions = statement.getQuerySource() == SqmQuerySource.CRITERIA && (sqmQuerySpec.getOrderByClause() != null || !sqmQuerySpec.getGroupByClauseExpressions().isEmpty());
}
final SqlAstProcessingState processingState;
if (trackAliasedNodePositions) {
processingState = new SqlAstQueryPartProcessingStateImpl(sqlQuerySpec, getCurrentProcessingState(), this, r -> new SqmAliasedNodePositionTracker(r, selectClause.getSelections()), currentClauseStack::getCurrent, deduplicateSelectionItems);
} else {
processingState = new SqlAstQueryPartProcessingStateImpl(sqlQuerySpec, getCurrentProcessingState(), this, currentClauseStack::getCurrent, deduplicateSelectionItems);
}
final SqmQueryPart<?> sqmQueryPart = currentSqmQueryPart;
final boolean originalDeduplicateSelectionItems = deduplicateSelectionItems;
currentSqmQueryPart = sqmQuerySpec;
// In sub-queries, we can never deduplicate the selection items as that might change semantics
deduplicateSelectionItems = false;
pushProcessingState(processingState);
queryTransformers.push(new ArrayList<>());
try {
// we want to visit the from-clause first
visitFromClause(sqmQuerySpec.getFromClause());
visitSelectClause(selectClause);
final SqmWhereClause whereClause = sqmQuerySpec.getWhereClause();
if (whereClause != null) {
sqlQuerySpec.applyPredicate(visitWhereClause(whereClause.getPredicate()));
}
sqlQuerySpec.setGroupByClauseExpressions(visitGroupByClause(sqmQuerySpec.getGroupByClauseExpressions()));
if (sqmQuerySpec.getHavingClausePredicate() != null) {
sqlQuerySpec.setHavingClauseRestrictions(visitHavingClause(sqmQuerySpec.getHavingClausePredicate()));
}
visitOrderByOffsetAndFetch(sqmQuerySpec, sqlQuerySpec);
if (topLevel && statement instanceof SqmSelectStatement<?>) {
if (orderByFragments != null) {
orderByFragments.forEach(entry -> entry.getKey().apply(sqlQuerySpec, entry.getValue(), this));
orderByFragments = null;
}
applyCollectionFilterPredicates(sqlQuerySpec);
}
QuerySpec finalQuerySpec = sqlQuerySpec;
for (QueryTransformer transformer : queryTransformers.getCurrent()) {
finalQuerySpec = transformer.transform(cteContainer, finalQuerySpec, this);
}
return finalQuerySpec;
} finally {
if (additionalRestrictions != null) {
sqlQuerySpec.applyPredicate(additionalRestrictions);
}
additionalRestrictions = originalAdditionalRestrictions;
popProcessingStateStack();
queryTransformers.pop();
currentSqmQueryPart = sqmQueryPart;
deduplicateSelectionItems = originalDeduplicateSelectionItems;
}
}
use of org.hibernate.query.sqm.tree.select.SqmQueryPart in project hibernate-orm by hibernate.
the class BaseSqmToSqlAstConverter method visitInsertSelectStatement.
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Insert-select statement
@Override
public InsertStatement visitInsertSelectStatement(SqmInsertSelectStatement<?> sqmStatement) {
final CteContainer cteContainer = this.visitCteContainer(sqmStatement);
final String entityName = sqmStatement.getTarget().getEntityName();
final EntityPersister entityDescriptor = creationContext.getSessionFactory().getRuntimeMetamodels().getMappingMetamodel().getEntityDescriptor(entityName);
assert entityDescriptor != null;
SqmQueryPart<?> selectQueryPart = sqmStatement.getSelectQueryPart();
pushProcessingState(new SqlAstProcessingStateImpl(null, this, r -> new SqmAliasedNodePositionTracker(r, selectQueryPart.getFirstQuerySpec().getSelectClause().getSelections()), getCurrentClauseStack()::getCurrent));
currentClauseStack.push(Clause.INSERT);
final InsertStatement insertStatement;
final AdditionalInsertValues additionalInsertValues;
try {
final NavigablePath rootPath = sqmStatement.getTarget().getNavigablePath();
final TableGroup rootTableGroup = entityDescriptor.createRootTableGroup(true, rootPath, sqmStatement.getTarget().getExplicitAlias(), () -> predicate -> additionalRestrictions = SqlAstTreeHelper.combinePredicates(additionalRestrictions, predicate), this, getCreationContext());
getFromClauseAccess().registerTableGroup(rootPath, rootTableGroup);
insertStatement = new InsertStatement(cteContainer, (NamedTableReference) rootTableGroup.getPrimaryTableReference(), Collections.emptyList());
additionalInsertValues = visitInsertionTargetPaths((assigable, references) -> insertStatement.addTargetColumnReferences(references), sqmStatement, entityDescriptor, rootTableGroup);
if (!rootTableGroup.getTableReferenceJoins().isEmpty() || !rootTableGroup.getTableGroupJoins().isEmpty()) {
throw new SemanticException("Not expecting multiple table references for an SQM INSERT-SELECT");
}
} finally {
popProcessingStateStack();
currentClauseStack.pop();
}
insertStatement.setSourceSelectStatement(visitQueryPart(selectQueryPart));
insertStatement.getSourceSelectStatement().visitQuerySpecs(querySpec -> {
final boolean appliedRowNumber = additionalInsertValues.applySelections(querySpec, creationContext.getSessionFactory());
// If this requires the special row number handling, it should use the mutation strategy
assert !appliedRowNumber;
});
return insertStatement;
}
Aggregations