Search in sources :

Example 16 with SqlTuple

use of org.hibernate.sql.ast.tree.expression.SqlTuple in project hibernate-orm by hibernate.

the class BaseSqmToSqlAstConverter method resolveGroupOrOrderByExpression.

protected Expression resolveGroupOrOrderByExpression(SqmExpression<?> groupByClauseExpression) {
    final int sqmPosition;
    if (groupByClauseExpression instanceof SqmAliasedNodeRef) {
        final int aliasedNodeOrdinal = ((SqmAliasedNodeRef) groupByClauseExpression).getPosition();
        sqmPosition = aliasedNodeOrdinal - 1;
    } else if (statement.getQuerySource() == SqmQuerySource.CRITERIA) {
        // In JPA Criteria we could be using the same expression object for the group/order by and select item
        // We try to find the select item position for this expression here which is not necessarily just an optimization.
        // This is vital to enable the support for parameters in these expressions.
        // Databases usually don't know if a parameter marker will have the same value as another parameter marker
        // and due to that, a database usually complains when seeing something like
        // `select ?, count(*) from dual group by ?` saying that there is a missing group by for the first `?`
        // To avoid this issue, we determine the position and let the SqlAstTranslator handle the rest.
        // Usually it will render `select ?, count(*) from dual group by 1` if supported
        // or force rendering the parameter as literal instead so that the database can see the grouping is fine
        final SqmQuerySpec<?> querySpec = currentSqmQueryPart.getFirstQuerySpec();
        sqmPosition = indexOfExpression(querySpec.getSelectClause().getSelections(), groupByClauseExpression);
    } else {
        sqmPosition = -1;
    }
    if (sqmPosition != -1) {
        final List<SqlSelection> selections = currentSqlSelectionCollector().getSelections(sqmPosition);
        assert selections != null : String.format(Locale.ROOT, "No SqlSelections for SQM position `%s`", sqmPosition);
        final List<Expression> expressions = new ArrayList<>(selections.size());
        OUTER: for (int i = 0; i < selections.size(); i++) {
            final SqlSelection selection = selections.get(i);
            // which is, just like the identifier itself, also registered as selection
            for (int j = 0; j < i; j++) {
                if (selections.get(j) == selection) {
                    continue OUTER;
                }
            }
            if (currentSqmQueryPart instanceof SqmQueryGroup<?>) {
                // Reusing the SqlSelection for query groups would be wrong because the aliases do no exist
                // So we have to use a literal expression in a new SqlSelection instance to refer to the position
                expressions.add(new SqlSelectionExpression(new SqlSelectionImpl(selection.getJdbcResultSetIndex(), selection.getValuesArrayPosition(), new QueryLiteral<>(selection.getValuesArrayPosition(), basicType(Integer.class)))));
            } else {
                expressions.add(new SqlSelectionExpression(selection));
            }
        }
        if (expressions.size() == 1) {
            return expressions.get(0);
        }
        return new SqlTuple(expressions, null);
    }
    return (Expression) groupByClauseExpression.accept(this);
}
Also used : SqmAliasedNodeRef(org.hibernate.query.sqm.tree.expression.SqmAliasedNodeRef) ArrayList(java.util.ArrayList) SqlSelectionExpression(org.hibernate.sql.ast.tree.expression.SqlSelectionExpression) SqlSelection(org.hibernate.sql.ast.spi.SqlSelection) BigInteger(java.math.BigInteger) QueryLiteral(org.hibernate.sql.ast.tree.expression.QueryLiteral) ConvertedQueryLiteral(org.hibernate.sql.ast.tree.expression.ConvertedQueryLiteral) BinaryArithmeticExpression(org.hibernate.sql.ast.tree.expression.BinaryArithmeticExpression) SqmModifiedSubQueryExpression(org.hibernate.query.sqm.tree.expression.SqmModifiedSubQueryExpression) SelfRenderingFunctionSqlAstExpression(org.hibernate.query.sqm.function.SelfRenderingFunctionSqlAstExpression) SelfRenderingAggregateFunctionSqlAstExpression(org.hibernate.query.sqm.function.SelfRenderingAggregateFunctionSqlAstExpression) CaseSearchedExpression(org.hibernate.sql.ast.tree.expression.CaseSearchedExpression) SelfRenderingSqlFragmentExpression(org.hibernate.sql.ast.tree.expression.SelfRenderingSqlFragmentExpression) Expression(org.hibernate.sql.ast.tree.expression.Expression) SelfRenderingExpression(org.hibernate.sql.ast.tree.expression.SelfRenderingExpression) SqmExpression(org.hibernate.query.sqm.tree.expression.SqmExpression) CaseSimpleExpression(org.hibernate.sql.ast.tree.expression.CaseSimpleExpression) SqlSelectionExpression(org.hibernate.sql.ast.tree.expression.SqlSelectionExpression) ModifiedSubQueryExpression(org.hibernate.sql.ast.tree.expression.ModifiedSubQueryExpression) SqlTuple(org.hibernate.sql.ast.tree.expression.SqlTuple) SqlSelectionImpl(org.hibernate.sql.results.internal.SqlSelectionImpl) SqmQuerySpec(org.hibernate.query.sqm.tree.select.SqmQuerySpec)

Example 17 with SqlTuple

use of org.hibernate.sql.ast.tree.expression.SqlTuple in project hibernate-orm by hibernate.

the class BaseSqmToSqlAstConverter method createCorrelatedAggregateSubQuery.

protected Expression createCorrelatedAggregateSubQuery(AbstractSqmSpecificPluralPartPath<?> pluralPartPath, boolean index, String function) {
    prepareReusablePath(pluralPartPath.getLhs(), () -> null);
    final PluralAttributeMapping pluralAttributeMapping = (PluralAttributeMapping) determineValueMapping(pluralPartPath.getPluralDomainPath());
    final FromClauseAccess parentFromClauseAccess = getFromClauseAccess();
    final QuerySpec subQuerySpec = new QuerySpec(false);
    pushProcessingState(new SqlAstQueryPartProcessingStateImpl(subQuerySpec, getCurrentProcessingState(), this, currentClauseStack::getCurrent, false));
    try {
        final TableGroup tableGroup = pluralAttributeMapping.createRootTableGroup(true, pluralPartPath.getNavigablePath(), null, () -> subQuerySpec::applyPredicate, this, creationContext);
        pluralAttributeMapping.applyBaseRestrictions(subQuerySpec::applyPredicate, tableGroup, true, getLoadQueryInfluencers().getEnabledFilters(), null, this);
        getFromClauseAccess().registerTableGroup(pluralPartPath.getNavigablePath(), tableGroup);
        registerPluralTableGroupParts(tableGroup);
        subQuerySpec.getFromClause().addRoot(tableGroup);
        final AbstractSqmSelfRenderingFunctionDescriptor functionDescriptor = (AbstractSqmSelfRenderingFunctionDescriptor) creationContext.getSessionFactory().getQueryEngine().getSqmFunctionRegistry().findFunctionDescriptor(function);
        final CollectionPart collectionPart = index ? pluralAttributeMapping.getIndexDescriptor() : pluralAttributeMapping.getElementDescriptor();
        final ModelPart modelPart;
        if (collectionPart instanceof EntityAssociationMapping) {
            modelPart = ((EntityAssociationMapping) collectionPart).getKeyTargetMatchPart();
        } else {
            modelPart = collectionPart;
        }
        final List<Expression> arguments = new ArrayList<>(1);
        final NavigablePath navigablePath = pluralPartPath.getNavigablePath();
        final int jdbcTypeCount = modelPart.getJdbcTypeCount();
        final List<Expression> tupleElements;
        if (jdbcTypeCount == 1) {
            tupleElements = arguments;
        } else {
            tupleElements = new ArrayList<>(jdbcTypeCount);
        }
        modelPart.forEachSelectable((selectionIndex, selectionMapping) -> tupleElements.add(new ColumnReference(tableGroup.resolveTableReference(navigablePath, selectionMapping.getContainingTableExpression()), selectionMapping, creationContext.getSessionFactory())));
        if (jdbcTypeCount != 1) {
            arguments.add(new SqlTuple(tupleElements, modelPart));
        }
        final Expression expression = new SelfRenderingAggregateFunctionSqlAstExpression(functionDescriptor.getName(), functionDescriptor, arguments, null, (ReturnableType<?>) functionDescriptor.getReturnTypeResolver().resolveFunctionReturnType(() -> null, arguments).getJdbcMapping(), modelPart);
        subQuerySpec.getSelectClause().addSqlSelection(new SqlSelectionImpl(1, 0, expression));
        NavigablePath parent = pluralPartPath.getPluralDomainPath().getNavigablePath().getParent();
        subQuerySpec.applyPredicate(pluralAttributeMapping.getKeyDescriptor().generateJoinPredicate(parentFromClauseAccess.findTableGroup(parent), tableGroup, getSqlExpressionResolver(), creationContext));
    } finally {
        popProcessingStateStack();
    }
    return subQuerySpec;
}
Also used : SelfRenderingAggregateFunctionSqlAstExpression(org.hibernate.query.sqm.function.SelfRenderingAggregateFunctionSqlAstExpression) 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) NavigablePath(org.hibernate.query.spi.NavigablePath) ConvertibleModelPart(org.hibernate.metamodel.mapping.ConvertibleModelPart) ModelPart(org.hibernate.metamodel.mapping.ModelPart) EntityValuedModelPart(org.hibernate.metamodel.mapping.EntityValuedModelPart) BasicValuedModelPart(org.hibernate.metamodel.mapping.BasicValuedModelPart) EmbeddableValuedModelPart(org.hibernate.metamodel.mapping.EmbeddableValuedModelPart) EntityAssociationMapping(org.hibernate.metamodel.mapping.EntityAssociationMapping) PluralAttributeMapping(org.hibernate.metamodel.mapping.PluralAttributeMapping) ArrayList(java.util.ArrayList) AbstractSqmSelfRenderingFunctionDescriptor(org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor) SqlAstQueryPartProcessingStateImpl(org.hibernate.query.sqm.sql.internal.SqlAstQueryPartProcessingStateImpl) FromClauseAccess(org.hibernate.sql.ast.spi.FromClauseAccess) BinaryArithmeticExpression(org.hibernate.sql.ast.tree.expression.BinaryArithmeticExpression) SqmModifiedSubQueryExpression(org.hibernate.query.sqm.tree.expression.SqmModifiedSubQueryExpression) SelfRenderingFunctionSqlAstExpression(org.hibernate.query.sqm.function.SelfRenderingFunctionSqlAstExpression) SelfRenderingAggregateFunctionSqlAstExpression(org.hibernate.query.sqm.function.SelfRenderingAggregateFunctionSqlAstExpression) CaseSearchedExpression(org.hibernate.sql.ast.tree.expression.CaseSearchedExpression) SelfRenderingSqlFragmentExpression(org.hibernate.sql.ast.tree.expression.SelfRenderingSqlFragmentExpression) Expression(org.hibernate.sql.ast.tree.expression.Expression) SelfRenderingExpression(org.hibernate.sql.ast.tree.expression.SelfRenderingExpression) SqmExpression(org.hibernate.query.sqm.tree.expression.SqmExpression) CaseSimpleExpression(org.hibernate.sql.ast.tree.expression.CaseSimpleExpression) SqlSelectionExpression(org.hibernate.sql.ast.tree.expression.SqlSelectionExpression) ModifiedSubQueryExpression(org.hibernate.sql.ast.tree.expression.ModifiedSubQueryExpression) SqlTuple(org.hibernate.sql.ast.tree.expression.SqlTuple) SqlSelectionImpl(org.hibernate.sql.results.internal.SqlSelectionImpl) SqmQuerySpec(org.hibernate.query.sqm.tree.select.SqmQuerySpec) QuerySpec(org.hibernate.sql.ast.tree.select.QuerySpec) EntityCollectionPart(org.hibernate.metamodel.mapping.internal.EntityCollectionPart) CollectionPart(org.hibernate.metamodel.mapping.CollectionPart) EmbeddedCollectionPart(org.hibernate.metamodel.mapping.internal.EmbeddedCollectionPart) ColumnReference(org.hibernate.sql.ast.tree.expression.ColumnReference)

Example 18 with SqlTuple

use of org.hibernate.sql.ast.tree.expression.SqlTuple in project hibernate-orm by hibernate.

the class RestrictedDeleteExecutionDelegate method deleteFromNonRootTableWithoutIdTable.

private int deleteFromNonRootTableWithoutIdTable(NamedTableReference targetTableReference, Supplier<Consumer<SelectableConsumer>> tableKeyColumnVisitationSupplier, SqlExpressionResolver sqlExpressionResolver, TableGroup rootTableGroup, QuerySpec matchingIdSubQuerySpec, JdbcParameterBindings jdbcParameterBindings, ExecutionContext executionContext) {
    assert targetTableReference != null;
    log.tracef("deleteFromNonRootTable - %s", targetTableReference.getTableExpression());
    final NamedTableReference deleteTableReference = new NamedTableReference(targetTableReference.getTableExpression(), DeleteStatement.DEFAULT_ALIAS, true, sessionFactory);
    final Predicate tableDeletePredicate;
    if (matchingIdSubQuerySpec == null) {
        tableDeletePredicate = null;
    } else {
        /*
			 * delete from sub_table
			 * where sub_id in (
			 * 		select root_id from root_table
			 * 		where {predicate}
			 * )
			 */
        /*
			 * Create the `sub_id` reference as the LHS of the in-subquery predicate
			 */
        final List<ColumnReference> deletingTableColumnRefs = new ArrayList<>();
        tableKeyColumnVisitationSupplier.get().accept((columnIndex, selection) -> {
            assert deleteTableReference.getTableReference(selection.getContainingTableExpression()) != null;
            final Expression expression = sqlExpressionResolver.resolveSqlExpression(SqlExpressionResolver.createColumnReferenceKey(deleteTableReference, selection.getSelectionExpression()), sqlAstProcessingState -> new ColumnReference(deleteTableReference, selection, sessionFactory));
            deletingTableColumnRefs.add((ColumnReference) expression);
        });
        final Expression deletingTableColumnRefsExpression;
        if (deletingTableColumnRefs.size() == 1) {
            deletingTableColumnRefsExpression = deletingTableColumnRefs.get(0);
        } else {
            deletingTableColumnRefsExpression = new SqlTuple(deletingTableColumnRefs, entityDescriptor.getIdentifierMapping());
        }
        tableDeletePredicate = new InSubQueryPredicate(deletingTableColumnRefsExpression, matchingIdSubQuerySpec, false);
    }
    final DeleteStatement sqlAstDelete = new DeleteStatement(deleteTableReference, tableDeletePredicate);
    final int rows = executeSqlDelete(sqlAstDelete, jdbcParameterBindings, executionContext);
    log.debugf("deleteFromNonRootTable - `%s` : %s rows", targetTableReference, rows);
    return rows;
}
Also used : NamedTableReference(org.hibernate.sql.ast.tree.from.NamedTableReference) Expression(org.hibernate.sql.ast.tree.expression.Expression) InSubQueryPredicate(org.hibernate.sql.ast.tree.predicate.InSubQueryPredicate) ArrayList(java.util.ArrayList) SqlTuple(org.hibernate.sql.ast.tree.expression.SqlTuple) SqmDeleteStatement(org.hibernate.query.sqm.tree.delete.SqmDeleteStatement) DeleteStatement(org.hibernate.sql.ast.tree.delete.DeleteStatement) InSubQueryPredicate(org.hibernate.sql.ast.tree.predicate.InSubQueryPredicate) Predicate(org.hibernate.sql.ast.tree.predicate.Predicate) ColumnReference(org.hibernate.sql.ast.tree.expression.ColumnReference)

Example 19 with SqlTuple

use of org.hibernate.sql.ast.tree.expression.SqlTuple in project hibernate-orm by hibernate.

the class AbstractSqlAstTranslator method determineLateralEmulationPredicate.

protected Predicate determineLateralEmulationPredicate(TableGroup tableGroup) {
    if (tableGroup.getPrimaryTableReference() instanceof QueryPartTableReference) {
        final QueryPartTableReference tableReference = (QueryPartTableReference) tableGroup.getPrimaryTableReference();
        final List<String> columnNames = tableReference.getColumnNames();
        final List<ColumnReference> columnReferences = new ArrayList<>(columnNames.size());
        final List<ColumnReference> subColumnReferences = new ArrayList<>(columnNames.size());
        final QueryPart queryPart = tableReference.getQueryPart();
        for (String columnName : columnNames) {
            columnReferences.add(new ColumnReference(tableReference, columnName, false, null, null, null, sessionFactory));
        }
        // The following optimization only makes sense if the necessary features are supported natively
        if ((columnReferences.size() == 1 || supportsRowValueConstructorSyntax()) && supportsDistinctFromPredicate()) {
            // ... x(c) on x.c is not distinct from (... fetch first 1 rows only)
            if (queryPart.getFetchClauseType() == FetchClauseType.ROWS_ONLY && queryPart.getFetchClauseExpression() instanceof QueryLiteral<?> && Integer.valueOf(1).equals(((QueryLiteral<?>) queryPart.getFetchClauseExpression()).getLiteralValue())) {
                return new ComparisonPredicate(new SqlTuple(columnReferences, tableGroup.getModelPart()), ComparisonOperator.NOT_DISTINCT_FROM, queryPart);
            }
        }
        // ... x(c) on exists(select x.c intersect ...)
        if (supportsIntersect()) {
            final QuerySpec lhsReferencesQuery = new QuerySpec(false);
            for (ColumnReference columnReference : columnReferences) {
                lhsReferencesQuery.getSelectClause().addSqlSelection(new SqlSelectionImpl(1, 0, columnReference));
            }
            final List<QueryPart> queryParts = new ArrayList<>(2);
            queryParts.add(lhsReferencesQuery);
            queryParts.add(queryPart);
            return new ExistsPredicate(new QueryGroup(false, SetOperator.INTERSECT, queryParts), false, getBooleanType());
        }
        // Double nested sub-query rendering if nothing else works
        // We try to avoid this as much as possible as it is not very efficient and some DBs don't like it
        // when a correlation happens in a sub-query that is not a direct child
        // ... x(c) on exists(select 1 from (...) synth_(c) where x.c = synth_.c)
        final QueryPartTableGroup subTableGroup = new QueryPartTableGroup(tableGroup.getNavigablePath(), (TableGroupProducer) tableGroup.getModelPart(), queryPart, "synth_", columnNames, false, true, sessionFactory);
        for (String columnName : columnNames) {
            subColumnReferences.add(new ColumnReference(subTableGroup.getPrimaryTableReference(), columnName, false, null, null, null, sessionFactory));
        }
        final QuerySpec existsQuery = new QuerySpec(false, 1);
        existsQuery.getSelectClause().addSqlSelection(new SqlSelectionImpl(1, 0, new QueryLiteral<>(1, getIntegerType())));
        existsQuery.getFromClause().addRoot(subTableGroup);
        existsQuery.applyPredicate(new ComparisonPredicate(new SqlTuple(columnReferences, tableGroup.getModelPart()), ComparisonOperator.NOT_DISTINCT_FROM, new SqlTuple(subColumnReferences, tableGroup.getModelPart())));
        return new ExistsPredicate(existsQuery, false, getBooleanType());
    }
    return null;
}
Also used : QueryPart(org.hibernate.sql.ast.tree.select.QueryPart) ExistsPredicate(org.hibernate.sql.ast.tree.predicate.ExistsPredicate) ArrayList(java.util.ArrayList) QueryPartTableGroup(org.hibernate.sql.ast.tree.from.QueryPartTableGroup) ComparisonPredicate(org.hibernate.sql.ast.tree.predicate.ComparisonPredicate) QueryGroup(org.hibernate.sql.ast.tree.select.QueryGroup) ConvertedQueryLiteral(org.hibernate.sql.ast.tree.expression.ConvertedQueryLiteral) QueryLiteral(org.hibernate.sql.ast.tree.expression.QueryLiteral) SqlTuple(org.hibernate.sql.ast.tree.expression.SqlTuple) SqlSelectionImpl(org.hibernate.sql.results.internal.SqlSelectionImpl) QuerySpec(org.hibernate.sql.ast.tree.select.QuerySpec) QueryPartTableReference(org.hibernate.sql.ast.tree.from.QueryPartTableReference) ColumnReference(org.hibernate.sql.ast.tree.expression.ColumnReference)

Example 20 with SqlTuple

use of org.hibernate.sql.ast.tree.expression.SqlTuple in project hibernate-orm by hibernate.

the class AbstractSqlAstTranslator method renderCommaSeparatedSelectExpression.

protected final void renderCommaSeparatedSelectExpression(Iterable<? extends SqlAstNode> expressions) {
    String separator = NO_SEPARATOR;
    for (SqlAstNode expression : expressions) {
        final SqlTuple sqlTuple = SqlTupleContainer.getSqlTuple(expression);
        if (sqlTuple != null) {
            for (Expression e : sqlTuple.getExpressions()) {
                appendSql(separator);
                renderSelectExpression(e);
                separator = COMA_SEPARATOR;
            }
        } else if (expression instanceof Expression) {
            appendSql(separator);
            renderSelectExpression((Expression) expression);
        } else {
            appendSql(separator);
            expression.accept(this);
        }
        separator = COMA_SEPARATOR;
    }
}
Also used : Expression(org.hibernate.sql.ast.tree.expression.Expression) BinaryArithmeticExpression(org.hibernate.sql.ast.tree.expression.BinaryArithmeticExpression) SelfRenderingExpression(org.hibernate.sql.ast.tree.expression.SelfRenderingExpression) OrderedSetAggregateFunctionExpression(org.hibernate.sql.ast.tree.expression.OrderedSetAggregateFunctionExpression) CaseSimpleExpression(org.hibernate.sql.ast.tree.expression.CaseSimpleExpression) SqlSelectionExpression(org.hibernate.sql.ast.tree.expression.SqlSelectionExpression) CaseSearchedExpression(org.hibernate.sql.ast.tree.expression.CaseSearchedExpression) ModifiedSubQueryExpression(org.hibernate.sql.ast.tree.expression.ModifiedSubQueryExpression) SqlTuple(org.hibernate.sql.ast.tree.expression.SqlTuple) SqlAstNode(org.hibernate.sql.ast.tree.SqlAstNode)

Aggregations

SqlTuple (org.hibernate.sql.ast.tree.expression.SqlTuple)34 Expression (org.hibernate.sql.ast.tree.expression.Expression)30 ColumnReference (org.hibernate.sql.ast.tree.expression.ColumnReference)20 ArrayList (java.util.ArrayList)17 SqlSelectionExpression (org.hibernate.sql.ast.tree.expression.SqlSelectionExpression)15 BinaryArithmeticExpression (org.hibernate.sql.ast.tree.expression.BinaryArithmeticExpression)14 CaseSearchedExpression (org.hibernate.sql.ast.tree.expression.CaseSearchedExpression)14 CaseSimpleExpression (org.hibernate.sql.ast.tree.expression.CaseSimpleExpression)14 ModifiedSubQueryExpression (org.hibernate.sql.ast.tree.expression.ModifiedSubQueryExpression)14 SelfRenderingExpression (org.hibernate.sql.ast.tree.expression.SelfRenderingExpression)14 NavigablePath (org.hibernate.query.spi.NavigablePath)12 TableReference (org.hibernate.sql.ast.tree.from.TableReference)11 SessionFactoryImplementor (org.hibernate.engine.spi.SessionFactoryImplementor)10 ModelPart (org.hibernate.metamodel.mapping.ModelPart)10 TableGroup (org.hibernate.sql.ast.tree.from.TableGroup)10 List (java.util.List)9 BasicValuedModelPart (org.hibernate.metamodel.mapping.BasicValuedModelPart)9 PluralAttributeMapping (org.hibernate.metamodel.mapping.PluralAttributeMapping)9 QuerySpec (org.hibernate.sql.ast.tree.select.QuerySpec)9 SqlSelectionImpl (org.hibernate.sql.results.internal.SqlSelectionImpl)9