Search in sources :

Example 1 with SortSpecification

use of org.hibernate.sql.ast.tree.select.SortSpecification in project hibernate-orm by hibernate.

the class AbstractSqlAstTranslator method renderOrderBy.

protected void renderOrderBy(boolean addWhitespace, List<SortSpecification> sortSpecifications) {
    if (sortSpecifications != null && !sortSpecifications.isEmpty()) {
        if (addWhitespace) {
            appendSql(WHITESPACE);
        }
        appendSql("order by ");
        clauseStack.push(Clause.ORDER);
        try {
            String separator = NO_SEPARATOR;
            for (SortSpecification sortSpecification : sortSpecifications) {
                appendSql(separator);
                visitSortSpecification(sortSpecification);
                separator = COMA_SEPARATOR;
            }
        } finally {
            clauseStack.pop();
        }
    }
}
Also used : SortSpecification(org.hibernate.sql.ast.tree.select.SortSpecification)

Example 2 with SortSpecification

use of org.hibernate.sql.ast.tree.select.SortSpecification in project hibernate-orm by hibernate.

the class ColumnReference method apply.

@Override
public void apply(QuerySpec ast, TableGroup tableGroup, String collation, String modelPartName, SortOrder sortOrder, NullPrecedence nullPrecedence, SqlAstCreationState creationState) {
    final Expression expression = resolve(ast, tableGroup, modelPartName, creationState);
    // SQL Server even reports a query error in this case
    if (ast.hasSortSpecifications()) {
        for (SortSpecification sortSpecification : ast.getSortSpecifications()) {
            if (sortSpecification.getSortExpression() == expression) {
                return;
            }
        }
    }
    final Expression sortExpression = OrderingExpression.applyCollation(expression, collation, creationState);
    ast.addSortSpecification(new SortSpecification(sortExpression, sortOrder, nullPrecedence));
}
Also used : Expression(org.hibernate.sql.ast.tree.expression.Expression) SortSpecification(org.hibernate.sql.ast.tree.select.SortSpecification)

Example 3 with SortSpecification

use of org.hibernate.sql.ast.tree.select.SortSpecification in project hibernate-orm by hibernate.

the class SelfRenderingOrderingExpression method apply.

@Override
public void apply(QuerySpec ast, TableGroup tableGroup, String collation, String modelPartName, SortOrder sortOrder, NullPrecedence nullPrecedence, SqlAstCreationState creationState) {
    final Expression expression = resolve(ast, tableGroup, modelPartName, creationState);
    // SQL Server even reports a query error in this case
    if (ast.hasSortSpecifications()) {
        for (SortSpecification sortSpecification : ast.getSortSpecifications()) {
            if (sortSpecification.getSortExpression() == expression) {
                return;
            }
        }
    }
    final Expression sortExpression = OrderingExpression.applyCollation(expression, collation, creationState);
    ast.addSortSpecification(new SortSpecification(sortExpression, sortOrder, nullPrecedence));
}
Also used : SelfRenderingSqlFragmentExpression(org.hibernate.sql.ast.tree.expression.SelfRenderingSqlFragmentExpression) Expression(org.hibernate.sql.ast.tree.expression.Expression) SortSpecification(org.hibernate.sql.ast.tree.select.SortSpecification)

Example 4 with SortSpecification

use of org.hibernate.sql.ast.tree.select.SortSpecification in project hibernate-orm by hibernate.

the class CteInsertHandler method addDmlCtes.

protected String addDmlCtes(CteContainer statement, CteStatement queryCte, List<Map.Entry<SqmCteTableColumn, Assignment>> assignments, boolean assignsId, MultiTableSqmMutationConverter sqmConverter, Map<SqmParameter<?>, List<List<JdbcParameter>>> parameterResolutions, SessionFactoryImplementor factory) {
    final TableGroup updatingTableGroup = sqmConverter.getMutatingTableGroup();
    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;
    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    // 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<Map.Entry<SqmCteTableColumn, Assignment>>> assignmentsByTable = CollectionHelper.mapOfSize(updatingTableGroup.getTableReferenceJoins().size() + 1);
    for (int i = 0; i < assignments.size(); i++) {
        final Map.Entry<SqmCteTableColumn, Assignment> entry = assignments.get(i);
        final Assignment assignment = entry.getValue();
        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, updatingTableGroup, 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<Map.Entry<SqmCteTableColumn, Assignment>> assignmentsForTable = assignmentsByTable.get(assignmentTableReference);
        if (assignmentsForTable == null) {
            assignmentsForTable = new ArrayList<>();
            assignmentsByTable.put(assignmentTableReference, assignmentsForTable);
        }
        assignmentsForTable.add(entry);
    }
    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    // Add the root insert as cte
    final AbstractEntityPersister persister = (AbstractEntityPersister) entityDescriptor.getEntityPersister();
    final String rootTableName = persister.getTableName(0);
    final TableReference rootTableReference = updatingTableGroup.getTableReference(updatingTableGroup.getNavigablePath(), rootTableName, true, true);
    final IdentifierGenerator identifierGenerator = entityDescriptor.getEntityPersister().getIdentifierGenerator();
    final List<Map.Entry<SqmCteTableColumn, Assignment>> tableAssignments = assignmentsByTable.get(rootTableReference);
    if ((tableAssignments == null || tableAssignments.isEmpty()) && !(identifierGenerator instanceof PostInsertIdentifierGenerator)) {
        throw new IllegalStateException("There must be at least a single root table assignment");
    }
    final int tableSpan = persister.getTableSpan();
    final String[] rootKeyColumns = persister.getKeyColumns(0);
    final List<CteColumn> keyCteColumns = queryCte.getCteTable().getCteColumns().subList(0, rootKeyColumns.length);
    for (int i = 0; i < tableSpan; i++) {
        final String tableExpression = persister.getTableName(i);
        final TableReference updatingTableReference = updatingTableGroup.getTableReference(updatingTableGroup.getNavigablePath(), tableExpression, true, true);
        final List<Map.Entry<SqmCteTableColumn, Assignment>> assignmentList = assignmentsByTable.get(updatingTableReference);
        final NamedTableReference dmlTableReference = resolveUnionTableReference(updatingTableReference, tableExpression);
        final String[] keyColumns = persister.getKeyColumns(i);
        final List<ColumnReference> returningColumnReferences = new ArrayList<>(keyColumns.length + (assignmentList == null ? 0 : assignmentList.size()));
        final List<ColumnReference> insertColumnReferences;
        final QuerySpec insertSelectSpec = new QuerySpec(true);
        CteStatement finalCteStatement = null;
        final CteTable dmlResultCte;
        if (i == 0 && !assignsId && identifierGenerator instanceof PostInsertIdentifierGenerator) {
            // Special handling for identity generation
            final String baseTableName = "base_" + queryCte.getCteTable().getTableExpression();
            insertSelectSpec.getFromClause().addRoot(new CteTableGroup(new NamedTableReference(baseTableName, "e", false, factory)));
            final CteColumn rowNumberColumn = queryCte.getCteTable().getCteColumns().get(queryCte.getCteTable().getCteColumns().size() - 1);
            final ColumnReference rowNumberColumnReference = new ColumnReference("e", rowNumberColumn.getColumnExpression(), false, null, null, rowNumberColumn.getJdbcMapping(), factory);
            // Insert in the same order as the original tuples came
            insertSelectSpec.addSortSpecification(new SortSpecification(rowNumberColumnReference, SortOrder.ASCENDING));
            final List<CteColumn> returningColumns = new ArrayList<>(keyCteColumns.size() + 1);
            returningColumns.addAll(keyCteColumns);
            dmlResultCte = new CteTable(getCteTableName(tableExpression, "base_"), returningColumns, factory);
            for (int j = 0; j < keyColumns.length; j++) {
                returningColumnReferences.add(new ColumnReference(dmlTableReference, keyColumns[j], false, null, null, null, factory));
            }
            insertColumnReferences = Collections.emptyList();
            final SelectStatement queryStatement = (SelectStatement) queryCte.getCteDefinition();
            final QuerySpec querySpec = queryStatement.getQuerySpec();
            final NavigablePath navigablePath = new NavigablePath(baseTableName);
            final TableGroup baseTableGroup = new TableGroupImpl(navigablePath, null, new NamedTableReference(baseTableName, "e", false, factory), null);
            final TableGroup rootInsertCteTableGroup = new CteTableGroup(new NamedTableReference(getCteTableName(tableExpression), "t", false, factory));
            baseTableGroup.addTableGroupJoin(new TableGroupJoin(rootInsertCteTableGroup.getNavigablePath(), SqlAstJoinType.INNER, rootInsertCteTableGroup, new ComparisonPredicate(rowNumberColumnReference, ComparisonOperator.EQUAL, new ColumnReference("t", rowNumberColumn.getColumnExpression(), false, null, null, rowNumberColumn.getJdbcMapping(), factory))));
            querySpec.getFromClause().addRoot(baseTableGroup);
            final List<CteColumn> cteColumns = queryCte.getCteTable().getCteColumns();
            // The id column in this case comes from the dml CTE
            final CteColumn idCteColumn = cteColumns.get(0);
            querySpec.getSelectClause().addSqlSelection(new SqlSelectionImpl(1, 0, new ColumnReference("t", idCteColumn.getColumnExpression(), false, null, null, idCteColumn.getJdbcMapping(), factory)));
            // The other columns come from the base CTE
            for (int j = 1; j < cteColumns.size(); j++) {
                final CteColumn cteColumn = cteColumns.get(j);
                querySpec.getSelectClause().addSqlSelection(new SqlSelectionImpl(1, 0, new ColumnReference("e", cteColumn.getColumnExpression(), false, null, null, cteColumn.getJdbcMapping(), factory)));
            }
            // Now build the final CTE statement
            final List<CteColumn> finalReturningColumns = new ArrayList<>(keyCteColumns.size() + 1);
            finalReturningColumns.addAll(keyCteColumns);
            finalReturningColumns.add(rowNumberColumn);
            final CteTable finalResultCte = new CteTable(getCteTableName(tableExpression), finalReturningColumns, factory);
            final QuerySpec finalResultQuery = new QuerySpec(true);
            finalResultQuery.getFromClause().addRoot(new CteTableGroup(new NamedTableReference(dmlResultCte.getTableExpression(), "e", false, factory)));
            // The id column in this case comes from the dml CTE
            final ColumnReference idColumnReference = new ColumnReference("e", idCteColumn.getColumnExpression(), false, null, null, idCteColumn.getJdbcMapping(), factory);
            finalResultQuery.getSelectClause().addSqlSelection(new SqlSelectionImpl(1, 0, idColumnReference));
            final BasicType<Integer> rowNumberType = sessionFactory.getTypeConfiguration().getBasicTypeForJavaType(Integer.class);
            finalResultQuery.getSelectClause().addSqlSelection(new SqlSelectionImpl(1, 0, new Over<>(new SelfRenderingFunctionSqlAstExpression("row_number", (appender, args, walker) -> appender.appendSql("row_number()"), Collections.emptyList(), rowNumberType, rowNumberType), Collections.emptyList(), Collections.emptyList())));
            finalResultQuery.addSortSpecification(new SortSpecification(idColumnReference, SortOrder.ASCENDING));
            final SelectStatement finalResultStatement = new SelectStatement(finalResultQuery);
            finalCteStatement = new CteStatement(finalResultCte, finalResultStatement);
        } else {
            insertSelectSpec.getFromClause().addRoot(new CteTableGroup(new NamedTableReference(queryCte.getCteTable().getTableExpression(), "e", false, factory)));
            dmlResultCte = new CteTable(getCteTableName(tableExpression), keyCteColumns, factory);
            for (int j = 0; j < keyColumns.length; j++) {
                returningColumnReferences.add(new ColumnReference(dmlTableReference, keyColumns[j], false, null, null, null, factory));
                insertSelectSpec.getSelectClause().addSqlSelection(new SqlSelectionImpl(1, 0, new ColumnReference("e", rootKeyColumns[j], false, null, null, null, factory)));
            }
            insertColumnReferences = returningColumnReferences;
        }
        final InsertStatement dmlStatement = new InsertStatement(dmlTableReference, returningColumnReferences);
        dmlStatement.addTargetColumnReferences(insertColumnReferences);
        if (assignmentList != null) {
            for (Map.Entry<SqmCteTableColumn, Assignment> entry : assignmentList) {
                final Assignment assignment = entry.getValue();
                // Skip the id mapping here as we handled that already
                if (assignment.getAssignedValue().getExpressionType() instanceof EntityIdentifierMapping) {
                    continue;
                }
                final List<ColumnReference> assignmentReferences = assignment.getAssignable().getColumnReferences();
                dmlStatement.addTargetColumnReferences(assignmentReferences);
                final int size = assignmentReferences.size();
                for (int j = 0; j < size; j++) {
                    final ColumnReference columnReference = assignmentReferences.get(j);
                    final String columnName = size > 1 ? entry.getKey().getColumnName() + '_' + i : entry.getKey().getColumnName();
                    insertSelectSpec.getSelectClause().addSqlSelection(new SqlSelectionImpl(1, 0, new ColumnReference("e", columnName, columnReference.isColumnExpressionFormula(), null, null, columnReference.getJdbcMapping(), factory)));
                }
            }
        }
        dmlStatement.setSourceSelectStatement(insertSelectSpec);
        statement.addCteStatement(new CteStatement(dmlResultCte, dmlStatement));
        if (finalCteStatement != null) {
            statement.addCteStatement(finalCteStatement);
        }
        if (i == 0 && !assignsId && identifierGenerator instanceof PostInsertIdentifierGenerator) {
            // Special handling for identity generation
            statement.addCteStatement(queryCte);
        }
    }
    return getCteTableName(rootTableName);
}
Also used : EntityPersister(org.hibernate.persister.entity.EntityPersister) AbstractEntityPersister(org.hibernate.persister.entity.AbstractEntityPersister) CteColumn(org.hibernate.sql.ast.tree.cte.CteColumn) CollectionHelper(org.hibernate.internal.util.collections.CollectionHelper) Arrays(java.util.Arrays) EntityPersister(org.hibernate.persister.entity.EntityPersister) Statement(org.hibernate.sql.ast.tree.Statement) SqlExpressible(org.hibernate.metamodel.mapping.SqlExpressible) BasicType(org.hibernate.type.BasicType) SqmCteTable(org.hibernate.query.sqm.tree.cte.SqmCteTable) SqmInsertValuesStatement(org.hibernate.query.sqm.tree.insert.SqmInsertValuesStatement) TableGroupJoin(org.hibernate.sql.ast.tree.from.TableGroupJoin) CteStatement(org.hibernate.sql.ast.tree.cte.CteStatement) Joinable(org.hibernate.persister.entity.Joinable) EntityMappingType(org.hibernate.metamodel.mapping.EntityMappingType) SqmExpression(org.hibernate.query.sqm.tree.expression.SqmExpression) Identifier(org.hibernate.boot.model.naming.Identifier) SqmJdbcExecutionContextAdapter(org.hibernate.query.sqm.internal.SqmJdbcExecutionContextAdapter) ComparisonPredicate(org.hibernate.sql.ast.tree.predicate.ComparisonPredicate) SqmUtil(org.hibernate.query.sqm.internal.SqmUtil) PostInsertIdentifierGenerator(org.hibernate.id.PostInsertIdentifierGenerator) Map(java.util.Map) ComparisonOperator(org.hibernate.query.sqm.ComparisonOperator) TableReferenceJoin(org.hibernate.sql.ast.tree.from.TableReferenceJoin) SessionFactoryImplementor(org.hibernate.engine.spi.SessionFactoryImplementor) SqmInsertSelectStatement(org.hibernate.query.sqm.tree.insert.SqmInsertSelectStatement) IdentifierGenerator(org.hibernate.id.IdentifierGenerator) Assignment(org.hibernate.sql.ast.tree.update.Assignment) IdentityHashMap(java.util.IdentityHashMap) SelfRenderingSqlFragmentExpression(org.hibernate.sql.ast.tree.expression.SelfRenderingSqlFragmentExpression) SelfRenderingFunctionSqlAstExpression(org.hibernate.query.sqm.function.SelfRenderingFunctionSqlAstExpression) TypeConfiguration(org.hibernate.type.spi.TypeConfiguration) Optimizer(org.hibernate.id.enhanced.Optimizer) NavigablePath(org.hibernate.query.spi.NavigablePath) DomainResult(org.hibernate.sql.results.graph.DomainResult) BasicValuedMapping(org.hibernate.metamodel.mapping.BasicValuedMapping) Expression(org.hibernate.sql.ast.tree.expression.Expression) BaseSqmToSqlAstConverter(org.hibernate.query.sqm.sql.BaseSqmToSqlAstConverter) BasicResult(org.hibernate.sql.results.graph.basic.BasicResult) SqlAstProcessingState(org.hibernate.sql.ast.spi.SqlAstProcessingState) EntityIdentifierMapping(org.hibernate.metamodel.mapping.EntityIdentifierMapping) SelectStatement(org.hibernate.sql.ast.tree.select.SelectStatement) InsertHandler(org.hibernate.query.sqm.mutation.internal.InsertHandler) List(java.util.List) Over(org.hibernate.sql.ast.tree.expression.Over) SqmParameter(org.hibernate.query.sqm.tree.expression.SqmParameter) AbstractEntityPersister(org.hibernate.persister.entity.AbstractEntityPersister) InsertStatement(org.hibernate.sql.ast.tree.insert.InsertStatement) QuerySpec(org.hibernate.sql.ast.tree.select.QuerySpec) MappingModelExpressible(org.hibernate.metamodel.mapping.MappingModelExpressible) TableGroupImpl(org.hibernate.query.results.TableGroupImpl) JdbcMapping(org.hibernate.metamodel.mapping.JdbcMapping) CteContainer(org.hibernate.sql.ast.tree.cte.CteContainer) CteMaterialization(org.hibernate.sql.ast.tree.cte.CteMaterialization) ColumnReference(org.hibernate.sql.ast.tree.expression.ColumnReference) OptimizableGenerator(org.hibernate.id.OptimizableGenerator) SemanticException(org.hibernate.query.SemanticException) SortOrder(org.hibernate.query.sqm.SortOrder) JdbcParameterBindings(org.hibernate.sql.exec.spi.JdbcParameterBindings) SortSpecification(org.hibernate.sql.ast.tree.select.SortSpecification) ArrayList(java.util.ArrayList) TableReference(org.hibernate.sql.ast.tree.from.TableReference) LinkedHashMap(java.util.LinkedHashMap) CteTable(org.hibernate.sql.ast.tree.cte.CteTable) NamedTableReference(org.hibernate.sql.ast.tree.from.NamedTableReference) MultiTableSqmMutationConverter(org.hibernate.query.sqm.mutation.internal.MultiTableSqmMutationConverter) SqmParameterMappingModelResolutionAccess(org.hibernate.query.sqm.spi.SqmParameterMappingModelResolutionAccess) CteColumn(org.hibernate.sql.ast.tree.cte.CteColumn) UnionTableReference(org.hibernate.sql.ast.tree.from.UnionTableReference) BiConsumer(java.util.function.BiConsumer) BinaryArithmeticExpression(org.hibernate.sql.ast.tree.expression.BinaryArithmeticExpression) BinaryArithmeticOperator(org.hibernate.query.sqm.BinaryArithmeticOperator) ValuesTableGroup(org.hibernate.sql.ast.tree.from.ValuesTableGroup) Values(org.hibernate.sql.ast.tree.insert.Values) BulkInsertionCapableIdentifierGenerator(org.hibernate.id.BulkInsertionCapableIdentifierGenerator) TemporaryTable(org.hibernate.dialect.temptable.TemporaryTable) ListResultsConsumer(org.hibernate.sql.results.spi.ListResultsConsumer) SqmStar(org.hibernate.query.sqm.tree.expression.SqmStar) CteTableGroup(org.hibernate.sql.ast.tree.cte.CteTableGroup) SqlAstTranslator(org.hibernate.sql.ast.SqlAstTranslator) JdbcServices(org.hibernate.engine.jdbc.spi.JdbcServices) QueryLiteral(org.hibernate.sql.ast.tree.expression.QueryLiteral) DomainQueryExecutionContext(org.hibernate.query.spi.DomainQueryExecutionContext) SqmCteTableColumn(org.hibernate.query.sqm.tree.cte.SqmCteTableColumn) AbstractMap(java.util.AbstractMap) JdbcParameter(org.hibernate.sql.ast.tree.expression.JdbcParameter) SqmInsertStatement(org.hibernate.query.sqm.tree.insert.SqmInsertStatement) QueryPart(org.hibernate.sql.ast.tree.select.QueryPart) SqlAstJoinType(org.hibernate.sql.ast.SqlAstJoinType) SqlSelectionImpl(org.hibernate.sql.results.internal.SqlSelectionImpl) Stack(org.hibernate.internal.util.collections.Stack) DomainParameterXref(org.hibernate.query.sqm.internal.DomainParameterXref) Collections(java.util.Collections) TableGroup(org.hibernate.sql.ast.tree.from.TableGroup) JdbcSelect(org.hibernate.sql.exec.spi.JdbcSelect) SqmValues(org.hibernate.query.sqm.tree.insert.SqmValues) NavigablePath(org.hibernate.query.spi.NavigablePath) ArrayList(java.util.ArrayList) ComparisonPredicate(org.hibernate.sql.ast.tree.predicate.ComparisonPredicate) InsertStatement(org.hibernate.sql.ast.tree.insert.InsertStatement) SqmInsertStatement(org.hibernate.query.sqm.tree.insert.SqmInsertStatement) Assignment(org.hibernate.sql.ast.tree.update.Assignment) TableGroupJoin(org.hibernate.sql.ast.tree.from.TableGroupJoin) SqmInsertSelectStatement(org.hibernate.query.sqm.tree.insert.SqmInsertSelectStatement) SelectStatement(org.hibernate.sql.ast.tree.select.SelectStatement) Over(org.hibernate.sql.ast.tree.expression.Over) TableReference(org.hibernate.sql.ast.tree.from.TableReference) NamedTableReference(org.hibernate.sql.ast.tree.from.NamedTableReference) UnionTableReference(org.hibernate.sql.ast.tree.from.UnionTableReference) SqmCteTable(org.hibernate.query.sqm.tree.cte.SqmCteTable) CteTable(org.hibernate.sql.ast.tree.cte.CteTable) CteStatement(org.hibernate.sql.ast.tree.cte.CteStatement) List(java.util.List) ArrayList(java.util.ArrayList) TableGroupImpl(org.hibernate.query.results.TableGroupImpl) EntityMappingType(org.hibernate.metamodel.mapping.EntityMappingType) ValuesTableGroup(org.hibernate.sql.ast.tree.from.ValuesTableGroup) CteTableGroup(org.hibernate.sql.ast.tree.cte.CteTableGroup) TableGroup(org.hibernate.sql.ast.tree.from.TableGroup) NamedTableReference(org.hibernate.sql.ast.tree.from.NamedTableReference) PostInsertIdentifierGenerator(org.hibernate.id.PostInsertIdentifierGenerator) CteTableGroup(org.hibernate.sql.ast.tree.cte.CteTableGroup) SqmCteTableColumn(org.hibernate.query.sqm.tree.cte.SqmCteTableColumn) SortSpecification(org.hibernate.sql.ast.tree.select.SortSpecification) Joinable(org.hibernate.persister.entity.Joinable) SelfRenderingFunctionSqlAstExpression(org.hibernate.query.sqm.function.SelfRenderingFunctionSqlAstExpression) EntityIdentifierMapping(org.hibernate.metamodel.mapping.EntityIdentifierMapping) SqlSelectionImpl(org.hibernate.sql.results.internal.SqlSelectionImpl) QuerySpec(org.hibernate.sql.ast.tree.select.QuerySpec) Map(java.util.Map) IdentityHashMap(java.util.IdentityHashMap) LinkedHashMap(java.util.LinkedHashMap) AbstractMap(java.util.AbstractMap) AbstractEntityPersister(org.hibernate.persister.entity.AbstractEntityPersister) ColumnReference(org.hibernate.sql.ast.tree.expression.ColumnReference) PostInsertIdentifierGenerator(org.hibernate.id.PostInsertIdentifierGenerator) IdentifierGenerator(org.hibernate.id.IdentifierGenerator) BulkInsertionCapableIdentifierGenerator(org.hibernate.id.BulkInsertionCapableIdentifierGenerator)

Example 5 with SortSpecification

use of org.hibernate.sql.ast.tree.select.SortSpecification in project hibernate-orm by hibernate.

the class InsertExecutionDelegate method insertRootTable.

private void insertRootTable(String tableExpression, int rows, String[] keyColumns, ExecutionContext executionContext) {
    final TableReference updatingTableReference = updatingTableGroup.getTableReference(updatingTableGroup.getNavigablePath(), tableExpression, true, true);
    final IdentifierGenerator identifierGenerator = entityDescriptor.getEntityPersister().getIdentifierGenerator();
    final List<Assignment> assignments = assignmentsByTable.get(updatingTableReference);
    if ((assignments == null || assignments.isEmpty()) && !(identifierGenerator instanceof PostInsertIdentifierGenerator)) {
        throw new IllegalStateException("There must be at least a single root table assignment");
    }
    final NamedTableReference dmlTableReference = resolveUnionTableReference(updatingTableReference, tableExpression);
    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    // Create the SQL AST and convert it into a JdbcOperation
    final QuerySpec querySpec = new QuerySpec(true);
    final NamedTableReference temporaryTableReference = new NamedTableReference(insertStatement.getTargetTable().getTableExpression(), updatingTableReference.getIdentificationVariable(), false, sessionFactory);
    final TableGroupImpl temporaryTableGroup = new TableGroupImpl(updatingTableGroup.getNavigablePath(), null, temporaryTableReference, entityDescriptor);
    querySpec.getFromClause().addRoot(temporaryTableGroup);
    final InsertStatement insertStatement = new InsertStatement(dmlTableReference);
    insertStatement.setSourceSelectStatement(querySpec);
    for (Assignment assignment : assignments) {
        insertStatement.addTargetColumnReferences(assignment.getAssignable().getColumnReferences());
        for (ColumnReference columnReference : assignment.getAssignable().getColumnReferences()) {
            querySpec.getSelectClause().addSqlSelection(new SqlSelectionImpl(1, 0, new ColumnReference(updatingTableReference.getIdentificationVariable(), columnReference.getColumnExpression(), false, null, null, columnReference.getJdbcMapping(), sessionFactory)));
        }
    }
    final JdbcServices jdbcServices = sessionFactory.getJdbcServices();
    final Map<Object, Object> entityTableToRootIdentity;
    if (identifierGenerator instanceof PostInsertIdentifierGenerator) {
        final BasicEntityIdentifierMapping identifierMapping = (BasicEntityIdentifierMapping) entityDescriptor.getIdentifierMapping();
        final QuerySpec idSelectQuerySpec = new QuerySpec(true);
        idSelectQuerySpec.getFromClause().addRoot(temporaryTableGroup);
        final ColumnReference columnReference = new ColumnReference((String) null, TemporaryTable.ENTITY_TABLE_IDENTITY_COLUMN, false, null, null, identifierMapping.getJdbcMapping(), sessionFactory);
        idSelectQuerySpec.getSelectClause().addSqlSelection(new SqlSelectionImpl(1, 0, columnReference));
        idSelectQuerySpec.addSortSpecification(new SortSpecification(columnReference, SortOrder.ASCENDING));
        final SelectStatement selectStatement = new SelectStatement(idSelectQuerySpec, Collections.singletonList(new BasicFetch<>(0, null, null, identifierMapping, null, FetchTiming.IMMEDIATE, null)));
        final JdbcSelect jdbcSelect = jdbcServices.getJdbcEnvironment().getSqlAstTranslatorFactory().buildSelectTranslator(sessionFactory, selectStatement).translate(null, executionContext.getQueryOptions());
        final List<Object> list = jdbcServices.getJdbcSelectExecutor().list(jdbcSelect, JdbcParameterBindings.NO_BINDINGS, executionContext, null, ListResultsConsumer.UniqueSemantic.NONE);
        entityTableToRootIdentity = new LinkedHashMap<>(list.size());
        for (Object o : list) {
            entityTableToRootIdentity.put(o, null);
        }
        querySpec.applyPredicate(new ComparisonPredicate(columnReference, ComparisonOperator.EQUAL, new JdbcParameterImpl(identifierMapping.getJdbcMapping())));
    } else {
        entityTableToRootIdentity = null;
        if (identifierGenerator instanceof OptimizableGenerator) {
            final Optimizer optimizer = ((OptimizableGenerator) identifierGenerator).getOptimizer();
            // but only if the target paths don't already contain the id
            if (optimizer != null && optimizer.getIncrementSize() > 1 && insertStatement.getTargetColumnReferences().stream().noneMatch(c -> keyColumns[0].equals(c.getColumnExpression()))) {
                final BasicEntityIdentifierMapping identifierMapping = (BasicEntityIdentifierMapping) entityDescriptor.getIdentifierMapping();
                final JdbcParameter rowNumber = new JdbcParameterImpl(identifierMapping.getJdbcMapping());
                final JdbcParameter rootIdentity = new JdbcParameterImpl(identifierMapping.getJdbcMapping());
                final List<Assignment> temporaryTableAssignments = new ArrayList<>(1);
                final ColumnReference idColumnReference = new ColumnReference((String) null, identifierMapping, sessionFactory);
                temporaryTableAssignments.add(new Assignment(idColumnReference, rootIdentity));
                final TemporaryTableColumn rowNumberColumn = entityTable.getColumns().get(entityTable.getColumns().size() - 1);
                final UpdateStatement updateStatement = new UpdateStatement(temporaryTableReference, temporaryTableAssignments, new ComparisonPredicate(new ColumnReference((String) null, rowNumberColumn.getColumnName(), false, null, null, rowNumberColumn.getJdbcMapping(), sessionFactory), ComparisonOperator.EQUAL, rowNumber));
                final JdbcUpdate jdbcUpdate = jdbcServices.getJdbcEnvironment().getSqlAstTranslatorFactory().buildUpdateTranslator(sessionFactory, updateStatement).translate(null, executionContext.getQueryOptions());
                final JdbcParameterBindings updateBindings = new JdbcParameterBindingsImpl(2);
                for (int i = 0; i < rows; i++) {
                    updateBindings.addBinding(rowNumber, new JdbcParameterBindingImpl(rowNumberColumn.getJdbcMapping(), i + 1));
                    updateBindings.addBinding(rootIdentity, new JdbcParameterBindingImpl(identifierMapping.getJdbcMapping(), identifierGenerator.generate(executionContext.getSession(), null)));
                    jdbcServices.getJdbcMutationExecutor().execute(jdbcUpdate, updateBindings, sql -> executionContext.getSession().getJdbcCoordinator().getStatementPreparer().prepareStatement(sql), (integer, preparedStatement) -> {
                    }, executionContext);
                }
                insertStatement.addTargetColumnReferences(new ColumnReference((String) null, keyColumns[0], false, null, null, identifierMapping.getJdbcMapping(), sessionFactory));
                querySpec.getSelectClause().addSqlSelection(new SqlSelectionImpl(1, 0, new ColumnReference(updatingTableReference.getIdentificationVariable(), idColumnReference.getColumnExpression(), false, null, null, idColumnReference.getJdbcMapping(), sessionFactory)));
            }
        }
    }
    final JdbcInsert jdbcInsert = jdbcServices.getJdbcEnvironment().getSqlAstTranslatorFactory().buildInsertTranslator(sessionFactory, insertStatement).translate(null, executionContext.getQueryOptions());
    if (identifierGenerator instanceof PostInsertIdentifierGenerator) {
        final PostInsertIdentifierGenerator generator = (PostInsertIdentifierGenerator) identifierGenerator;
        final boolean generatedKeysEnabled = sessionFactory.getSessionFactoryOptions().isGetGeneratedKeysEnabled();
        final InsertGeneratedIdentifierDelegate identifierDelegate = generator.getInsertGeneratedIdentifierDelegate((PostInsertIdentityPersister) entityDescriptor.getEntityPersister(), jdbcServices.getDialect(), generatedKeysEnabled);
        final String finalSql = identifierDelegate.prepareIdentifierGeneratingInsert(jdbcInsert.getSql());
        final BasicEntityIdentifierMapping identifierMapping = (BasicEntityIdentifierMapping) entityDescriptor.getIdentifierMapping();
        final ValueBinder jdbcValueBinder = identifierMapping.getJdbcMapping().getJdbcValueBinder();
        for (Map.Entry<Object, Object> entry : entityTableToRootIdentity.entrySet()) {
            final Object rootIdentity = identifierDelegate.performInsert(finalSql, executionContext.getSession(), new Binder() {

                @Override
                public void bindValues(PreparedStatement ps) throws SQLException {
                    jdbcValueBinder.bind(ps, entry.getKey(), 1, executionContext.getSession());
                }

                @Override
                public Object getEntity() {
                    return null;
                }
            });
            entry.setValue(rootIdentity);
        }
        final JdbcParameter entityIdentity = new JdbcParameterImpl(identifierMapping.getJdbcMapping());
        final JdbcParameter rootIdentity = new JdbcParameterImpl(identifierMapping.getJdbcMapping());
        final List<Assignment> temporaryTableAssignments = new ArrayList<>(1);
        temporaryTableAssignments.add(new Assignment(new ColumnReference((String) null, identifierMapping, sessionFactory), rootIdentity));
        final UpdateStatement updateStatement = new UpdateStatement(temporaryTableReference, temporaryTableAssignments, new ComparisonPredicate(new ColumnReference((String) null, TemporaryTable.ENTITY_TABLE_IDENTITY_COLUMN, false, null, null, identifierMapping.getJdbcMapping(), sessionFactory), ComparisonOperator.EQUAL, entityIdentity));
        final JdbcUpdate jdbcUpdate = jdbcServices.getJdbcEnvironment().getSqlAstTranslatorFactory().buildUpdateTranslator(sessionFactory, updateStatement).translate(null, executionContext.getQueryOptions());
        final JdbcParameterBindings updateBindings = new JdbcParameterBindingsImpl(2);
        for (Map.Entry<Object, Object> entry : entityTableToRootIdentity.entrySet()) {
            updateBindings.addBinding(entityIdentity, new JdbcParameterBindingImpl(identifierMapping.getJdbcMapping(), entry.getKey()));
            updateBindings.addBinding(rootIdentity, new JdbcParameterBindingImpl(identifierMapping.getJdbcMapping(), entry.getValue()));
            jdbcServices.getJdbcMutationExecutor().execute(jdbcUpdate, updateBindings, sql -> executionContext.getSession().getJdbcCoordinator().getStatementPreparer().prepareStatement(sql), (integer, preparedStatement) -> {
            }, executionContext);
        }
    } else {
        jdbcServices.getJdbcMutationExecutor().execute(jdbcInsert, JdbcParameterBindings.NO_BINDINGS, sql -> executionContext.getSession().getJdbcCoordinator().getStatementPreparer().prepareStatement(sql), (integer, preparedStatement) -> {
        }, executionContext);
    }
}
Also used : CollectionHelper(org.hibernate.internal.util.collections.CollectionHelper) ExecutionContext(org.hibernate.sql.exec.spi.ExecutionContext) ValueBinder(org.hibernate.type.descriptor.ValueBinder) EntityMappingType(org.hibernate.metamodel.mapping.EntityMappingType) ComparisonPredicate(org.hibernate.sql.ast.tree.predicate.ComparisonPredicate) SqmUtil(org.hibernate.query.sqm.internal.SqmUtil) PostInsertIdentifierGenerator(org.hibernate.id.PostInsertIdentifierGenerator) Map(java.util.Map) JdbcParameterImpl(org.hibernate.sql.exec.internal.JdbcParameterImpl) Binder(org.hibernate.id.insert.Binder) ComparisonOperator(org.hibernate.query.sqm.ComparisonOperator) SessionFactoryImplementor(org.hibernate.engine.spi.SessionFactoryImplementor) IdentifierGenerator(org.hibernate.id.IdentifierGenerator) Assignable(org.hibernate.sql.ast.tree.update.Assignable) Assignment(org.hibernate.sql.ast.tree.update.Assignment) Optimizer(org.hibernate.id.enhanced.Optimizer) PreparedStatement(java.sql.PreparedStatement) UpdateStatement(org.hibernate.sql.ast.tree.update.UpdateStatement) SelectStatement(org.hibernate.sql.ast.tree.select.SelectStatement) List(java.util.List) JdbcUpdate(org.hibernate.sql.exec.spi.JdbcUpdate) SqmParameter(org.hibernate.query.sqm.tree.expression.SqmParameter) AbstractEntityPersister(org.hibernate.persister.entity.AbstractEntityPersister) InsertStatement(org.hibernate.sql.ast.tree.insert.InsertStatement) QuerySpec(org.hibernate.sql.ast.tree.select.QuerySpec) TemporaryTableColumn(org.hibernate.dialect.temptable.TemporaryTableColumn) MappingModelExpressible(org.hibernate.metamodel.mapping.MappingModelExpressible) SharedSessionContractImplementor(org.hibernate.engine.spi.SharedSessionContractImplementor) BasicEntityIdentifierMapping(org.hibernate.metamodel.mapping.BasicEntityIdentifierMapping) JdbcParameterBindingsImpl(org.hibernate.sql.exec.internal.JdbcParameterBindingsImpl) TableGroupImpl(org.hibernate.query.results.TableGroupImpl) ColumnReference(org.hibernate.sql.ast.tree.expression.ColumnReference) OptimizableGenerator(org.hibernate.id.OptimizableGenerator) Function(java.util.function.Function) SemanticException(org.hibernate.query.SemanticException) SortOrder(org.hibernate.query.sqm.SortOrder) JdbcParameterBindings(org.hibernate.sql.exec.spi.JdbcParameterBindings) BasicFetch(org.hibernate.sql.results.graph.basic.BasicFetch) SortSpecification(org.hibernate.sql.ast.tree.select.SortSpecification) ArrayList(java.util.ArrayList) TableReference(org.hibernate.sql.ast.tree.from.TableReference) LinkedHashMap(java.util.LinkedHashMap) NamedTableReference(org.hibernate.sql.ast.tree.from.NamedTableReference) SQLException(java.sql.SQLException) MultiTableSqmMutationConverter(org.hibernate.query.sqm.mutation.internal.MultiTableSqmMutationConverter) JdbcInsert(org.hibernate.sql.exec.spi.JdbcInsert) SqmParameterMappingModelResolutionAccess(org.hibernate.query.sqm.spi.SqmParameterMappingModelResolutionAccess) UnionTableReference(org.hibernate.sql.ast.tree.from.UnionTableReference) PostInsertIdentityPersister(org.hibernate.id.PostInsertIdentityPersister) FetchTiming(org.hibernate.engine.FetchTiming) InsertGeneratedIdentifierDelegate(org.hibernate.id.insert.InsertGeneratedIdentifierDelegate) TemporaryTable(org.hibernate.dialect.temptable.TemporaryTable) ListResultsConsumer(org.hibernate.sql.results.spi.ListResultsConsumer) ModelPartContainer(org.hibernate.metamodel.mapping.ModelPartContainer) JdbcServices(org.hibernate.engine.jdbc.spi.JdbcServices) DomainQueryExecutionContext(org.hibernate.query.spi.DomainQueryExecutionContext) JdbcParameter(org.hibernate.sql.ast.tree.expression.JdbcParameter) JdbcParameterBindingImpl(org.hibernate.sql.exec.internal.JdbcParameterBindingImpl) SqmInsertStatement(org.hibernate.query.sqm.tree.insert.SqmInsertStatement) SqlSelectionImpl(org.hibernate.sql.results.internal.SqlSelectionImpl) DomainParameterXref(org.hibernate.query.sqm.internal.DomainParameterXref) Collections(java.util.Collections) TableGroup(org.hibernate.sql.ast.tree.from.TableGroup) JdbcSelect(org.hibernate.sql.exec.spi.JdbcSelect) SQLException(java.sql.SQLException) OptimizableGenerator(org.hibernate.id.OptimizableGenerator) Optimizer(org.hibernate.id.enhanced.Optimizer) ArrayList(java.util.ArrayList) JdbcServices(org.hibernate.engine.jdbc.spi.JdbcServices) TemporaryTableColumn(org.hibernate.dialect.temptable.TemporaryTableColumn) InsertStatement(org.hibernate.sql.ast.tree.insert.InsertStatement) SqmInsertStatement(org.hibernate.query.sqm.tree.insert.SqmInsertStatement) ComparisonPredicate(org.hibernate.sql.ast.tree.predicate.ComparisonPredicate) Assignment(org.hibernate.sql.ast.tree.update.Assignment) SelectStatement(org.hibernate.sql.ast.tree.select.SelectStatement) ValueBinder(org.hibernate.type.descriptor.ValueBinder) Binder(org.hibernate.id.insert.Binder) TableReference(org.hibernate.sql.ast.tree.from.TableReference) NamedTableReference(org.hibernate.sql.ast.tree.from.NamedTableReference) UnionTableReference(org.hibernate.sql.ast.tree.from.UnionTableReference) JdbcUpdate(org.hibernate.sql.exec.spi.JdbcUpdate) TableGroupImpl(org.hibernate.query.results.TableGroupImpl) JdbcParameterImpl(org.hibernate.sql.exec.internal.JdbcParameterImpl) BasicFetch(org.hibernate.sql.results.graph.basic.BasicFetch) JdbcSelect(org.hibernate.sql.exec.spi.JdbcSelect) UpdateStatement(org.hibernate.sql.ast.tree.update.UpdateStatement) NamedTableReference(org.hibernate.sql.ast.tree.from.NamedTableReference) JdbcParameterBindingsImpl(org.hibernate.sql.exec.internal.JdbcParameterBindingsImpl) JdbcParameter(org.hibernate.sql.ast.tree.expression.JdbcParameter) JdbcParameterBindingImpl(org.hibernate.sql.exec.internal.JdbcParameterBindingImpl) PreparedStatement(java.sql.PreparedStatement) BasicEntityIdentifierMapping(org.hibernate.metamodel.mapping.BasicEntityIdentifierMapping) InsertGeneratedIdentifierDelegate(org.hibernate.id.insert.InsertGeneratedIdentifierDelegate) PostInsertIdentifierGenerator(org.hibernate.id.PostInsertIdentifierGenerator) JdbcInsert(org.hibernate.sql.exec.spi.JdbcInsert) SortSpecification(org.hibernate.sql.ast.tree.select.SortSpecification) SqlSelectionImpl(org.hibernate.sql.results.internal.SqlSelectionImpl) ValueBinder(org.hibernate.type.descriptor.ValueBinder) QuerySpec(org.hibernate.sql.ast.tree.select.QuerySpec) Map(java.util.Map) LinkedHashMap(java.util.LinkedHashMap) PostInsertIdentifierGenerator(org.hibernate.id.PostInsertIdentifierGenerator) IdentifierGenerator(org.hibernate.id.IdentifierGenerator) ColumnReference(org.hibernate.sql.ast.tree.expression.ColumnReference) JdbcParameterBindings(org.hibernate.sql.exec.spi.JdbcParameterBindings)

Aggregations

SortSpecification (org.hibernate.sql.ast.tree.select.SortSpecification)15 Expression (org.hibernate.sql.ast.tree.expression.Expression)9 ArrayList (java.util.ArrayList)6 SelfRenderingFunctionSqlAstExpression (org.hibernate.query.sqm.function.SelfRenderingFunctionSqlAstExpression)6 SqmSortSpecification (org.hibernate.query.sqm.tree.select.SqmSortSpecification)6 ColumnReference (org.hibernate.sql.ast.tree.expression.ColumnReference)5 Over (org.hibernate.sql.ast.tree.expression.Over)5 List (java.util.List)4 SelfRenderingSqlFragmentExpression (org.hibernate.sql.ast.tree.expression.SelfRenderingSqlFragmentExpression)4 QuerySpec (org.hibernate.sql.ast.tree.select.QuerySpec)4 Collections (java.util.Collections)3 Map (java.util.Map)3 SessionFactoryImplementor (org.hibernate.engine.spi.SessionFactoryImplementor)3 NavigablePath (org.hibernate.query.spi.NavigablePath)3 ComparisonOperator (org.hibernate.query.sqm.ComparisonOperator)3 SelfRenderingAggregateFunctionSqlAstExpression (org.hibernate.query.sqm.function.SelfRenderingAggregateFunctionSqlAstExpression)3 JdbcParameter (org.hibernate.sql.ast.tree.expression.JdbcParameter)3 TableGroup (org.hibernate.sql.ast.tree.from.TableGroup)3 ComparisonPredicate (org.hibernate.sql.ast.tree.predicate.ComparisonPredicate)3 SqlSelectionImpl (org.hibernate.sql.results.internal.SqlSelectionImpl)3