Search in sources :

Example 1 with SqmUpdateStatement

use of org.hibernate.query.sqm.tree.update.SqmUpdateStatement in project hibernate-orm by hibernate.

the class SemanticQueryBuilder method visitUpdateStatement.

@Override
public SqmUpdateStatement<R> visitUpdateStatement(HqlParser.UpdateStatementContext ctx) {
    final boolean versioned = !(ctx.getChild(1) instanceof HqlParser.TargetEntityContext);
    final int dmlTargetIndex = versioned ? 2 : 1;
    final HqlParser.TargetEntityContext dmlTargetContext = (HqlParser.TargetEntityContext) ctx.getChild(dmlTargetIndex);
    final SqmRoot<R> root = visitTargetEntity(dmlTargetContext);
    if (root.getReferencedPathSource() instanceof SqmPolymorphicRootDescriptor<?>) {
        throw new SemanticException(String.format("Target type '%s' in update statement is not an entity", root.getReferencedPathSource().getHibernateEntityName()));
    }
    final SqmUpdateStatement<R> updateStatement = new SqmUpdateStatement<>(root, creationContext.getNodeBuilder());
    parameterCollector = updateStatement;
    final SqmDmlCreationProcessingState processingState = new SqmDmlCreationProcessingState(updateStatement, this);
    processingStateStack.push(processingState);
    processingState.getPathRegistry().register(root);
    try {
        updateStatement.versioned(versioned);
        final HqlParser.SetClauseContext setClauseCtx = (HqlParser.SetClauseContext) ctx.getChild(dmlTargetIndex + 1);
        for (ParseTree subCtx : setClauseCtx.children) {
            if (subCtx instanceof HqlParser.AssignmentContext) {
                final HqlParser.AssignmentContext assignmentContext = (HqlParser.AssignmentContext) subCtx;
                updateStatement.applyAssignment(consumeDomainPath((HqlParser.SimplePathContext) assignmentContext.getChild(0)), (SqmExpression<?>) assignmentContext.getChild(2).accept(this));
            }
        }
        if (dmlTargetIndex + 2 <= ctx.getChildCount()) {
            updateStatement.applyPredicate(visitWhereClause((HqlParser.WhereClauseContext) ctx.getChild(dmlTargetIndex + 2)));
        }
        return updateStatement;
    } finally {
        processingStateStack.pop();
    }
}
Also used : SqmUpdateStatement(org.hibernate.query.sqm.tree.update.SqmUpdateStatement) TIMEZONE_HOUR(org.hibernate.query.sqm.TemporalUnit.TIMEZONE_HOUR) WEEK_OF_YEAR(org.hibernate.query.sqm.TemporalUnit.WEEK_OF_YEAR) DAY_OF_YEAR(org.hibernate.query.sqm.TemporalUnit.DAY_OF_YEAR) IDENTIFIER(org.hibernate.grammars.hql.HqlParser.IDENTIFIER) HqlParser(org.hibernate.grammars.hql.HqlParser) SqmPolymorphicRootDescriptor(org.hibernate.query.sqm.tree.domain.SqmPolymorphicRootDescriptor) SqmDmlCreationProcessingState(org.hibernate.query.sqm.internal.SqmDmlCreationProcessingState) ParseTree(org.antlr.v4.runtime.tree.ParseTree) SemanticException(org.hibernate.query.SemanticException)

Example 2 with SqmUpdateStatement

use of org.hibernate.query.sqm.tree.update.SqmUpdateStatement in project hibernate-orm by hibernate.

the class QuerySqmImpl method buildUpdateQueryPlan.

private NonSelectQueryPlan buildUpdateQueryPlan() {
    // noinspection rawtypes
    final SqmUpdateStatement sqmUpdate = (SqmUpdateStatement) getSqmStatement();
    final String entityNameToUpdate = sqmUpdate.getTarget().getReferencedPathSource().getHibernateEntityName();
    final EntityPersister entityDescriptor = getSessionFactory().getRuntimeMetamodels().getMappingMetamodel().getEntityDescriptor(entityNameToUpdate);
    final SqmMultiTableMutationStrategy multiTableStrategy = entityDescriptor.getSqmMultiTableMutationStrategy();
    if (multiTableStrategy == null) {
        return new SimpleUpdateQueryPlan(sqmUpdate, domainParameterXref);
    } else {
        return new MultiTableUpdateQueryPlan(sqmUpdate, domainParameterXref, multiTableStrategy);
    }
}
Also used : SqmUpdateStatement(org.hibernate.query.sqm.tree.update.SqmUpdateStatement) EntityPersister(org.hibernate.persister.entity.EntityPersister) SqmMultiTableMutationStrategy(org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy)

Example 3 with SqmUpdateStatement

use of org.hibernate.query.sqm.tree.update.SqmUpdateStatement in project hibernate-orm by hibernate.

the class CteUpdateHandler method addDmlCtes.

@Override
protected void addDmlCtes(CteContainer statement, CteStatement idSelectCte, MultiTableSqmMutationConverter sqmConverter, Map<SqmParameter, List<JdbcParameter>> parameterResolutions, SessionFactoryImplementor factory) {
    final TableGroup updatingTableGroup = sqmConverter.getMutatingTableGroup();
    final SqmUpdateStatement<?> updateStatement = (SqmUpdateStatement<?>) getSqmDeleteOrUpdateStatement();
    final EntityMappingType entityDescriptor = getEntityDescriptor();
    final EntityPersister entityPersister = entityDescriptor.getEntityPersister();
    final String rootEntityName = entityPersister.getRootEntityName();
    final EntityPersister rootEntityDescriptor = factory.getRuntimeMetamodels().getMappingMetamodel().getEntityDescriptor(rootEntityName);
    final String hierarchyRootTableName = ((Joinable) rootEntityDescriptor).getTableName();
    final TableReference hierarchyRootTableReference = updatingTableGroup.resolveTableReference(updatingTableGroup.getNavigablePath(), hierarchyRootTableName);
    assert hierarchyRootTableReference != null;
    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    // visit the set-clause using our special converter, collecting
    // information about the assignments
    final SqmSetClause setClause = updateStatement.getSetClause();
    final List<Assignment> assignments = new ArrayList<>(setClause.getAssignments().size());
    final Map<SqmParameter, MappingModelExpressible> paramTypeResolutions = new LinkedHashMap<>();
    sqmConverter.visitSetClause(setClause, assignments::add, (sqmParam, mappingType, jdbcParameters) -> {
        parameterResolutions.put(sqmParam, jdbcParameters);
        paramTypeResolutions.put(sqmParam, mappingType);
    });
    sqmConverter.addVersionedAssignment(assignments::add, updateStatement);
    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    // cross-reference the TableReference by alias.  The TableGroup already
    // cross-references it by name, but the ColumnReference only has the alias
    final Map<String, TableReference> tableReferenceByAlias = CollectionHelper.mapOfSize(updatingTableGroup.getTableReferenceJoins().size() + 1);
    collectTableReference(updatingTableGroup.getPrimaryTableReference(), tableReferenceByAlias::put);
    for (int i = 0; i < updatingTableGroup.getTableReferenceJoins().size(); i++) {
        collectTableReference(updatingTableGroup.getTableReferenceJoins().get(i), tableReferenceByAlias::put);
    }
    final Map<TableReference, List<Assignment>> assignmentsByTable = CollectionHelper.mapOfSize(updatingTableGroup.getTableReferenceJoins().size() + 1);
    for (int i = 0; i < assignments.size(); i++) {
        final Assignment assignment = assignments.get(i);
        final List<ColumnReference> assignmentColumnRefs = assignment.getAssignable().getColumnReferences();
        TableReference assignmentTableReference = null;
        for (int c = 0; c < assignmentColumnRefs.size(); c++) {
            final ColumnReference columnReference = assignmentColumnRefs.get(c);
            final TableReference tableReference = resolveTableReference(columnReference, tableReferenceByAlias);
            // TODO: this could be fixed by introducing joins to DML statements
            if (assignmentTableReference != null && !assignmentTableReference.equals(tableReference)) {
                throw new IllegalStateException("Assignment referred to columns from multiple tables");
            }
            assignmentTableReference = tableReference;
        }
        assert assignmentTableReference != null;
        List<Assignment> assignmentsForTable = assignmentsByTable.get(assignmentTableReference);
        if (assignmentsForTable == null) {
            assignmentsForTable = new ArrayList<>();
            assignmentsByTable.put(assignmentTableReference, assignmentsForTable);
        }
        assignmentsForTable.add(assignment);
    }
    getEntityDescriptor().visitConstraintOrderedTables((tableExpression, tableColumnsVisitationSupplier) -> {
        final CteTable dmlResultCte = new CteTable(getCteTableName(tableExpression), idSelectCte.getCteTable().getCteColumns(), factory);
        final TableReference updatingTableReference = updatingTableGroup.getTableReference(updatingTableGroup.getNavigablePath(), tableExpression, true, true);
        final List<Assignment> assignmentList = assignmentsByTable.get(updatingTableReference);
        if (assignmentList == null) {
            return;
        }
        final NamedTableReference dmlTableReference = resolveUnionTableReference(updatingTableReference, tableExpression);
        final List<ColumnReference> columnReferences = new ArrayList<>(idSelectCte.getCteTable().getCteColumns().size());
        tableColumnsVisitationSupplier.get().accept((index, selectable) -> columnReferences.add(new ColumnReference(dmlTableReference, selectable, factory)));
        final MutationStatement dmlStatement = new UpdateStatement(dmlTableReference, assignmentList, createIdSubQueryPredicate(columnReferences, idSelectCte, factory), columnReferences);
        statement.addCteStatement(new CteStatement(dmlResultCte, dmlStatement));
    });
}
Also used : EntityPersister(org.hibernate.persister.entity.EntityPersister) MappingModelExpressible(org.hibernate.metamodel.mapping.MappingModelExpressible) ArrayList(java.util.ArrayList) LinkedHashMap(java.util.LinkedHashMap) Assignment(org.hibernate.sql.ast.tree.update.Assignment) TableReference(org.hibernate.sql.ast.tree.from.TableReference) NamedTableReference(org.hibernate.sql.ast.tree.from.NamedTableReference) SqmCteTable(org.hibernate.query.sqm.tree.cte.SqmCteTable) CteTable(org.hibernate.sql.ast.tree.cte.CteTable) CteStatement(org.hibernate.sql.ast.tree.cte.CteStatement) ArrayList(java.util.ArrayList) List(java.util.List) SqmSetClause(org.hibernate.query.sqm.tree.update.SqmSetClause) EntityMappingType(org.hibernate.metamodel.mapping.EntityMappingType) SqmUpdateStatement(org.hibernate.query.sqm.tree.update.SqmUpdateStatement) UpdateStatement(org.hibernate.sql.ast.tree.update.UpdateStatement) TableGroup(org.hibernate.sql.ast.tree.from.TableGroup) NamedTableReference(org.hibernate.sql.ast.tree.from.NamedTableReference) SqmUpdateStatement(org.hibernate.query.sqm.tree.update.SqmUpdateStatement) MutationStatement(org.hibernate.sql.ast.tree.MutationStatement) Joinable(org.hibernate.persister.entity.Joinable) SqmParameter(org.hibernate.query.sqm.tree.expression.SqmParameter) ColumnReference(org.hibernate.sql.ast.tree.expression.ColumnReference)

Example 4 with SqmUpdateStatement

use of org.hibernate.query.sqm.tree.update.SqmUpdateStatement in project hibernate-orm by hibernate.

the class BaseSqmToSqlAstConverter method visitUpdateStatement.

// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Update statement
@Override
public UpdateStatement visitUpdateStatement(SqmUpdateStatement<?> sqmStatement) {
    final CteContainer cteContainer = this.visitCteContainer(sqmStatement);
    final SqmRoot<?> sqmTarget = sqmStatement.getTarget();
    final String entityName = sqmTarget.getEntityName();
    final EntityPersister entityDescriptor = getCreationContext().getSessionFactory().getRuntimeMetamodels().getMappingMetamodel().getEntityDescriptor(entityName);
    assert entityDescriptor != null;
    pushProcessingState(new SqlAstProcessingStateImpl(getCurrentProcessingState(), this, getCurrentClauseStack()::getCurrent));
    try {
        final NavigablePath rootPath = sqmTarget.getNavigablePath();
        final TableGroup rootTableGroup = entityDescriptor.createRootTableGroup(true, rootPath, sqmStatement.getRoot().getAlias(), () -> predicate -> additionalRestrictions = SqlAstTreeHelper.combinePredicates(additionalRestrictions, predicate), this, getCreationContext());
        if (!rootTableGroup.getTableReferenceJoins().isEmpty()) {
            throw new HibernateException("Not expecting multiple table references for an SQM UPDATE");
        }
        if (sqmTarget.hasJoins()) {
            throw new HibernateException("SQM UPDATE does not support explicit joins");
        }
        getFromClauseAccess().registerTableGroup(rootPath, rootTableGroup);
        final List<Assignment> assignments = visitSetClause(sqmStatement.getSetClause());
        addVersionedAssignment(assignments::add, sqmStatement);
        FilterHelper.applyBaseRestrictions((filterPredicate) -> additionalRestrictions = filterPredicate, entityDescriptor, rootTableGroup, AbstractSqlAstTranslator.rendersTableReferenceAlias(Clause.UPDATE), getLoadQueryInfluencers(), this);
        Predicate suppliedPredicate = null;
        final SqmWhereClause whereClause = sqmStatement.getWhereClause();
        if (whereClause != null) {
            suppliedPredicate = visitWhereClause(whereClause.getPredicate());
        }
        return new UpdateStatement(cteContainer, (NamedTableReference) rootTableGroup.getPrimaryTableReference(), assignments, SqlAstTreeHelper.combinePredicates(suppliedPredicate, additionalRestrictions), Collections.emptyList());
    } finally {
        popProcessingStateStack();
    }
}
Also used : EntityPersister(org.hibernate.persister.entity.EntityPersister) SingleTableEntityPersister(org.hibernate.persister.entity.SingleTableEntityPersister) AbstractEntityPersister(org.hibernate.persister.entity.AbstractEntityPersister) SqmCteContainer(org.hibernate.query.sqm.tree.cte.SqmCteContainer) CteContainer(org.hibernate.sql.ast.tree.cte.CteContainer) UpdateStatement(org.hibernate.sql.ast.tree.update.UpdateStatement) SqmUpdateStatement(org.hibernate.query.sqm.tree.update.SqmUpdateStatement) NavigablePath(org.hibernate.query.spi.NavigablePath) VirtualTableGroup(org.hibernate.sql.ast.tree.from.VirtualTableGroup) LazyTableGroup(org.hibernate.sql.ast.tree.from.LazyTableGroup) TableGroup(org.hibernate.sql.ast.tree.from.TableGroup) CorrelatedTableGroup(org.hibernate.sql.ast.tree.from.CorrelatedTableGroup) CorrelatedPluralTableGroup(org.hibernate.sql.ast.tree.from.CorrelatedPluralTableGroup) PluralTableGroup(org.hibernate.sql.ast.tree.from.PluralTableGroup) QueryPartTableGroup(org.hibernate.sql.ast.tree.from.QueryPartTableGroup) HibernateException(org.hibernate.HibernateException) SqlAstProcessingStateImpl(org.hibernate.query.sqm.sql.internal.SqlAstProcessingStateImpl) InSubQueryPredicate(org.hibernate.sql.ast.tree.predicate.InSubQueryPredicate) SqmBooleanExpressionPredicate(org.hibernate.query.sqm.tree.predicate.SqmBooleanExpressionPredicate) SelfRenderingPredicate(org.hibernate.sql.ast.tree.predicate.SelfRenderingPredicate) NegatedPredicate(org.hibernate.sql.ast.tree.predicate.NegatedPredicate) LikePredicate(org.hibernate.sql.ast.tree.predicate.LikePredicate) BetweenPredicate(org.hibernate.sql.ast.tree.predicate.BetweenPredicate) SqmPredicate(org.hibernate.query.sqm.tree.predicate.SqmPredicate) SqmNegatedPredicate(org.hibernate.query.sqm.tree.predicate.SqmNegatedPredicate) ExistsPredicate(org.hibernate.sql.ast.tree.predicate.ExistsPredicate) SqmAndPredicate(org.hibernate.query.sqm.tree.predicate.SqmAndPredicate) SqmMemberOfPredicate(org.hibernate.query.sqm.tree.predicate.SqmMemberOfPredicate) SqmLikePredicate(org.hibernate.query.sqm.tree.predicate.SqmLikePredicate) SqmExistsPredicate(org.hibernate.query.sqm.tree.predicate.SqmExistsPredicate) SqmOrPredicate(org.hibernate.query.sqm.tree.predicate.SqmOrPredicate) SqmNullnessPredicate(org.hibernate.query.sqm.tree.predicate.SqmNullnessPredicate) SqmComparisonPredicate(org.hibernate.query.sqm.tree.predicate.SqmComparisonPredicate) SqmGroupedPredicate(org.hibernate.query.sqm.tree.predicate.SqmGroupedPredicate) SqmInListPredicate(org.hibernate.query.sqm.tree.predicate.SqmInListPredicate) ComparisonPredicate(org.hibernate.sql.ast.tree.predicate.ComparisonPredicate) NullnessPredicate(org.hibernate.sql.ast.tree.predicate.NullnessPredicate) SqmBetweenPredicate(org.hibernate.query.sqm.tree.predicate.SqmBetweenPredicate) GroupedPredicate(org.hibernate.sql.ast.tree.predicate.GroupedPredicate) BooleanExpressionPredicate(org.hibernate.sql.ast.tree.predicate.BooleanExpressionPredicate) InListPredicate(org.hibernate.sql.ast.tree.predicate.InListPredicate) SqmInSubQueryPredicate(org.hibernate.query.sqm.tree.predicate.SqmInSubQueryPredicate) SqmEmptinessPredicate(org.hibernate.query.sqm.tree.predicate.SqmEmptinessPredicate) Predicate(org.hibernate.sql.ast.tree.predicate.Predicate) Assignment(org.hibernate.sql.ast.tree.update.Assignment) SqmAssignment(org.hibernate.query.sqm.tree.update.SqmAssignment) SqmWhereClause(org.hibernate.query.sqm.tree.predicate.SqmWhereClause)

Aggregations

SqmUpdateStatement (org.hibernate.query.sqm.tree.update.SqmUpdateStatement)4 EntityPersister (org.hibernate.persister.entity.EntityPersister)3 TableGroup (org.hibernate.sql.ast.tree.from.TableGroup)2 Assignment (org.hibernate.sql.ast.tree.update.Assignment)2 UpdateStatement (org.hibernate.sql.ast.tree.update.UpdateStatement)2 ArrayList (java.util.ArrayList)1 LinkedHashMap (java.util.LinkedHashMap)1 List (java.util.List)1 ParseTree (org.antlr.v4.runtime.tree.ParseTree)1 HibernateException (org.hibernate.HibernateException)1 HqlParser (org.hibernate.grammars.hql.HqlParser)1 IDENTIFIER (org.hibernate.grammars.hql.HqlParser.IDENTIFIER)1 EntityMappingType (org.hibernate.metamodel.mapping.EntityMappingType)1 MappingModelExpressible (org.hibernate.metamodel.mapping.MappingModelExpressible)1 AbstractEntityPersister (org.hibernate.persister.entity.AbstractEntityPersister)1 Joinable (org.hibernate.persister.entity.Joinable)1 SingleTableEntityPersister (org.hibernate.persister.entity.SingleTableEntityPersister)1 SemanticException (org.hibernate.query.SemanticException)1 NavigablePath (org.hibernate.query.spi.NavigablePath)1 DAY_OF_YEAR (org.hibernate.query.sqm.TemporalUnit.DAY_OF_YEAR)1