use of org.hibernate.query.hql.spi.SqmCreationProcessingState 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.hql.spi.SqmCreationProcessingState in project hibernate-orm by hibernate.
the class SemanticQueryBuilder method visitInsertStatement.
@Override
public SqmInsertStatement<R> visitInsertStatement(HqlParser.InsertStatementContext ctx) {
final int dmlTargetIndex;
if (ctx.getChild(1) instanceof HqlParser.TargetEntityContext) {
dmlTargetIndex = 1;
} else {
dmlTargetIndex = 2;
}
final HqlParser.TargetEntityContext dmlTargetContext = (HqlParser.TargetEntityContext) ctx.getChild(dmlTargetIndex);
final HqlParser.TargetFieldsContext targetFieldsSpecContext = (HqlParser.TargetFieldsContext) ctx.getChild(dmlTargetIndex + 1);
final SqmRoot<R> root = visitTargetEntity(dmlTargetContext);
if (root.getReferencedPathSource() instanceof SqmPolymorphicRootDescriptor<?>) {
throw new SemanticException(String.format("Target type '%s' in insert statement is not an entity", root.getReferencedPathSource().getHibernateEntityName()));
}
final HqlParser.QueryExpressionContext queryExpressionContext = ctx.queryExpression();
if (queryExpressionContext != null) {
final SqmInsertSelectStatement<R> insertStatement = new SqmInsertSelectStatement<>(root, creationContext.getNodeBuilder());
parameterCollector = insertStatement;
final SqmDmlCreationProcessingState processingState = new SqmDmlCreationProcessingState(insertStatement, this);
processingStateStack.push(processingState);
try {
queryExpressionContext.accept(this);
final SqmCreationProcessingState stateFieldsProcessingState = new SqmCreationProcessingStateImpl(insertStatement, this);
stateFieldsProcessingState.getPathRegistry().register(root);
processingStateStack.push(stateFieldsProcessingState);
try {
for (HqlParser.SimplePathContext stateFieldCtx : targetFieldsSpecContext.simplePath()) {
final SqmPath<?> stateField = (SqmPath<?>) visitSimplePath(stateFieldCtx);
// todo : validate each resolved stateField...
insertStatement.addInsertTargetStateField(stateField);
}
} finally {
processingStateStack.pop();
}
return insertStatement;
} finally {
processingStateStack.pop();
}
} else {
final SqmInsertValuesStatement<R> insertStatement = new SqmInsertValuesStatement<>(root, creationContext.getNodeBuilder());
parameterCollector = insertStatement;
final SqmDmlCreationProcessingState processingState = new SqmDmlCreationProcessingState(insertStatement, this);
processingStateStack.push(processingState);
processingState.getPathRegistry().register(root);
try {
final HqlParser.ValuesListContext valuesListContext = ctx.valuesList();
for (int i = 1; i < valuesListContext.getChildCount(); i += 2) {
final ParseTree values = valuesListContext.getChild(i);
final SqmValues sqmValues = new SqmValues();
for (int j = 1; j < values.getChildCount(); j += 2) {
sqmValues.getExpressions().add((SqmExpression<?>) values.getChild(j).accept(this));
}
insertStatement.getValuesList().add(sqmValues);
}
for (HqlParser.SimplePathContext stateFieldCtx : targetFieldsSpecContext.simplePath()) {
final SqmPath<?> stateField = (SqmPath<?>) visitSimplePath(stateFieldCtx);
// todo : validate each resolved stateField...
insertStatement.addInsertTargetStateField(stateField);
}
return insertStatement;
} finally {
processingStateStack.pop();
}
}
}
use of org.hibernate.query.hql.spi.SqmCreationProcessingState 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;
}
use of org.hibernate.query.hql.spi.SqmCreationProcessingState 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.hql.spi.SqmCreationProcessingState in project hibernate-orm by hibernate.
the class QualifiedJoinPathConsumer method resolveBase.
private ConsumerDelegate resolveBase(String identifier, boolean isTerminal) {
final SqmCreationProcessingState processingState = creationState.getCurrentProcessingState();
final SqmPathRegistry pathRegistry = processingState.getPathRegistry();
final SqmFrom<?, Object> pathRootByAlias = pathRegistry.findFromByAlias(identifier, true);
if (pathRootByAlias != null) {
if (isTerminal) {
throw new SemanticException("Cannot join to root '" + identifier + "'");
}
return new AttributeJoinDelegate(pathRootByAlias, joinType, fetch, alias, creationState);
}
final SqmFrom<?, Object> pathRootByExposedNavigable = pathRegistry.findFromExposing(identifier);
if (pathRootByExposedNavigable != null) {
return new AttributeJoinDelegate(createJoin(pathRootByExposedNavigable, identifier, isTerminal), joinType, fetch, alias, creationState);
}
return new ExpectingEntityJoinDelegate(identifier, isTerminal, sqmRoot, joinType, alias, fetch, creationState);
}
Aggregations