Search in sources :

Example 1 with SqmSortSpecification

use of org.hibernate.query.sqm.tree.select.SqmSortSpecification in project hibernate-orm by hibernate.

the class SemanticQueryBuilder method applyOverClause.

private SqmExpression<?> applyOverClause(HqlParser.OverClauseContext ctx, SqmFunction<?> function) {
    final List<SqmExpression<?>> partitions;
    final List<SqmSortSpecification> orderList;
    final FrameMode mode;
    final FrameKind startKind;
    final SqmExpression<?> startExpression;
    final FrameKind endKind;
    final SqmExpression<?> endExpression;
    final FrameExclusion exclusion;
    int index = 2;
    if (ctx.getChild(index) instanceof HqlParser.PartitionClauseContext) {
        final ParseTree subCtx = ctx.getChild(index);
        partitions = new ArrayList<>((subCtx.getChildCount() >> 1) - 1);
        for (int i = 2; i < subCtx.getChildCount(); i += 2) {
            partitions.add((SqmExpression<?>) subCtx.getChild(i).accept(this));
        }
        index++;
    } else {
        partitions = Collections.emptyList();
    }
    if (index < ctx.getChildCount() && ctx.getChild(index) instanceof HqlParser.OrderByClauseContext) {
        orderList = visitOrderByClause((HqlParser.OrderByClauseContext) ctx.getChild(index)).getSortSpecifications();
        index++;
    } else {
        orderList = Collections.emptyList();
    }
    if (index < ctx.getChildCount() && ctx.getChild(index) instanceof HqlParser.FrameClauseContext) {
        final ParseTree frameCtx = ctx.getChild(index);
        switch(((TerminalNode) frameCtx.getChild(0)).getSymbol().getType()) {
            case HqlParser.RANGE:
                mode = FrameMode.RANGE;
                break;
            case HqlParser.ROWS:
                mode = FrameMode.ROWS;
                break;
            case HqlParser.GROUPS:
                mode = FrameMode.GROUPS;
                break;
            default:
                throw new IllegalArgumentException("Unexpected frame mode: " + frameCtx.getChild(0));
        }
        final int frameStartIndex;
        if (frameCtx.getChild(1) instanceof TerminalNode) {
            frameStartIndex = 2;
            endKind = getFrameKind(frameCtx.getChild(4));
            endExpression = endKind == FrameKind.OFFSET_FOLLOWING || endKind == FrameKind.OFFSET_PRECEDING ? (SqmExpression<?>) frameCtx.getChild(4).getChild(0).accept(this) : null;
        } else {
            frameStartIndex = 1;
            endKind = FrameKind.CURRENT_ROW;
            endExpression = null;
        }
        startKind = getFrameKind(frameCtx.getChild(frameStartIndex));
        startExpression = startKind == FrameKind.OFFSET_FOLLOWING || startKind == FrameKind.OFFSET_PRECEDING ? (SqmExpression<?>) frameCtx.getChild(frameStartIndex).getChild(0).accept(this) : null;
        final ParseTree lastChild = frameCtx.getChild(frameCtx.getChildCount() - 1);
        if (lastChild instanceof HqlParser.FrameExclusionContext) {
            switch(((TerminalNode) lastChild.getChild(1)).getSymbol().getType()) {
                case HqlParser.CURRENT:
                    exclusion = FrameExclusion.CURRENT_ROW;
                    break;
                case HqlParser.GROUP:
                    exclusion = FrameExclusion.GROUP;
                    break;
                case HqlParser.TIES:
                    exclusion = FrameExclusion.TIES;
                    break;
                case HqlParser.NO:
                    exclusion = FrameExclusion.NO_OTHERS;
                    break;
                default:
                    throw new IllegalArgumentException("Unexpected frame exclusion: " + lastChild);
            }
        } else {
            exclusion = FrameExclusion.NO_OTHERS;
        }
    } else {
        mode = FrameMode.ROWS;
        startKind = FrameKind.UNBOUNDED_PRECEDING;
        startExpression = null;
        endKind = FrameKind.CURRENT_ROW;
        endExpression = null;
        exclusion = FrameExclusion.NO_OTHERS;
    }
    return new SqmOver<>(function, partitions, orderList, mode, startKind, startExpression, endKind, endExpression, exclusion);
}
Also used : FrameExclusion(org.hibernate.query.sqm.FrameExclusion) FrameKind(org.hibernate.query.sqm.FrameKind) SqmSortSpecification(org.hibernate.query.sqm.tree.select.SqmSortSpecification) SqmExpression(org.hibernate.query.sqm.tree.expression.SqmExpression) HqlParser(org.hibernate.grammars.hql.HqlParser) FrameMode(org.hibernate.query.sqm.FrameMode) TerminalNode(org.antlr.v4.runtime.tree.TerminalNode) SqmOver(org.hibernate.query.sqm.tree.expression.SqmOver) ParseTree(org.antlr.v4.runtime.tree.ParseTree)

Example 2 with SqmSortSpecification

use of org.hibernate.query.sqm.tree.select.SqmSortSpecification in project hibernate-orm by hibernate.

the class InverseDistributionWindowEmulation method generateSqmOrderedSetAggregateFunctionExpression.

@Override
public <T> SelfRenderingSqmOrderedSetAggregateFunction<T> generateSqmOrderedSetAggregateFunctionExpression(List<? extends SqmTypedNode<?>> arguments, SqmPredicate filter, SqmOrderByClause withinGroupClause, ReturnableType<T> impliedResultType, QueryEngine queryEngine, TypeConfiguration typeConfiguration) {
    return new SelfRenderingInverseDistributionFunction<>(arguments, filter, withinGroupClause, impliedResultType, queryEngine) {

        @Override
        public Expression convertToSqlAst(SqmToSqlAstConverter walker) {
            final Clause currentClause = walker.getCurrentClauseStack().getCurrent();
            if (currentClause == Clause.OVER) {
                return super.convertToSqlAst(walker);
            } else if (currentClause != Clause.SELECT) {
                throw new IllegalArgumentException("Can't emulate [" + getName() + "] in clause " + currentClause + ". Only the SELECT clause is supported!");
            }
            final ReturnableType<?> resultType = resolveResultType(walker.getCreationContext().getMappingMetamodel().getTypeConfiguration());
            List<SqlAstNode> arguments = resolveSqlAstArguments(getArguments(), walker);
            ArgumentsValidator argumentsValidator = getArgumentsValidator();
            if (argumentsValidator != null) {
                argumentsValidator.validateSqlTypes(arguments, getFunctionName());
            }
            List<SortSpecification> withinGroup;
            if (this.getWithinGroup() == null) {
                withinGroup = Collections.emptyList();
            } else {
                walker.getCurrentClauseStack().push(Clause.ORDER);
                try {
                    final List<SqmSortSpecification> sortSpecifications = this.getWithinGroup().getSortSpecifications();
                    withinGroup = new ArrayList<>(sortSpecifications.size());
                    for (SqmSortSpecification sortSpecification : sortSpecifications) {
                        final SortSpecification specification = (SortSpecification) walker.visitSortSpecification(sortSpecification);
                        if (specification != null) {
                            withinGroup.add(specification);
                        }
                    }
                } finally {
                    walker.getCurrentClauseStack().pop();
                }
            }
            final SelfRenderingFunctionSqlAstExpression function = new SelfRenderingOrderedSetAggregateFunctionSqlAstExpression(getFunctionName(), getRenderingSupport(), arguments, getFilter() == null ? null : (Predicate) getFilter().accept(walker), withinGroup, resultType, getMappingModelExpressible(walker, resultType));
            final Over<Object> windowFunction = new Over<>(function, new ArrayList<>(), Collections.emptyList());
            walker.registerQueryTransformer(new AggregateWindowEmulationQueryTransformer(windowFunction, withinGroup, null));
            return windowFunction;
        }
    };
}
Also used : SqlAstNode(org.hibernate.sql.ast.tree.SqlAstNode) SqmToSqlAstConverter(org.hibernate.query.sqm.sql.SqmToSqlAstConverter) SqmSortSpecification(org.hibernate.query.sqm.tree.select.SqmSortSpecification) SqmPredicate(org.hibernate.query.sqm.tree.predicate.SqmPredicate) Predicate(org.hibernate.sql.ast.tree.predicate.Predicate) Over(org.hibernate.sql.ast.tree.expression.Over) SortSpecification(org.hibernate.sql.ast.tree.select.SortSpecification) SqmSortSpecification(org.hibernate.query.sqm.tree.select.SqmSortSpecification) SelfRenderingFunctionSqlAstExpression(org.hibernate.query.sqm.function.SelfRenderingFunctionSqlAstExpression) SelfRenderingOrderedSetAggregateFunctionSqlAstExpression(org.hibernate.query.sqm.function.SelfRenderingOrderedSetAggregateFunctionSqlAstExpression) Clause(org.hibernate.sql.ast.Clause) SqmOrderByClause(org.hibernate.query.sqm.tree.select.SqmOrderByClause) ArgumentsValidator(org.hibernate.query.sqm.produce.function.ArgumentsValidator)

Example 3 with SqmSortSpecification

use of org.hibernate.query.sqm.tree.select.SqmSortSpecification in project hibernate-orm by hibernate.

the class SqmOver method copy.

@Override
public SqmOver<T> copy(SqmCopyContext context) {
    final SqmOver<T> existing = context.getCopy(this);
    if (existing != null) {
        return existing;
    }
    final List<SqmExpression<?>> partitions = new ArrayList<>(this.partitions.size());
    for (SqmExpression<?> partition : this.partitions) {
        partitions.add(partition.copy(context));
    }
    final List<SqmSortSpecification> orderList = new ArrayList<>(this.orderList.size());
    for (SqmSortSpecification sortSpecification : this.orderList) {
        orderList.add(sortSpecification.copy(context));
    }
    final SqmOver<T> over = context.registerCopy(this, new SqmOver<>(expression.copy(context), partitions, orderList, mode, startKind, startExpression == null ? null : startExpression.copy(context), endKind, endExpression == null ? null : endExpression.copy(context), exclusion));
    copyTo(over, context);
    return over;
}
Also used : ArrayList(java.util.ArrayList) SqmSortSpecification(org.hibernate.query.sqm.tree.select.SqmSortSpecification)

Example 4 with SqmSortSpecification

use of org.hibernate.query.sqm.tree.select.SqmSortSpecification in project hibernate-orm by hibernate.

the class BaseSqmToSqlAstConverter method visitOrderByOffsetAndFetch.

protected void visitOrderByOffsetAndFetch(SqmQueryPart<?> sqmQueryPart, QueryPart sqlQueryPart) {
    if (sqmQueryPart.getOrderByClause() != null) {
        currentClauseStack.push(Clause.ORDER);
        inferrableTypeAccessStack.push(() -> null);
        try {
            for (SqmSortSpecification sortSpecification : sqmQueryPart.getOrderByClause().getSortSpecifications()) {
                final SortSpecification specification = visitSortSpecification(sortSpecification);
                if (specification != null) {
                    sqlQueryPart.addSortSpecification(specification);
                }
            }
        } finally {
            inferrableTypeAccessStack.pop();
            currentClauseStack.pop();
        }
    }
    if (!containsCollectionFetches || !currentClauseStack.isEmpty()) {
        // Strip off the root offset and limit expressions in case the query contains collection fetches to retain
        // the proper cardinality. We could implement pagination for single select statements differently in this
        // case by using a subquery e.g. `... where alias in (select subAlias from ... limit ...)`
        // or use window functions e.g. `select ... from (select ..., dense_rank() over(order by ..., id) rn from ...) tmp where tmp.rn between ...`
        // but these transformations/translations are non-trivial and can be done later
        inferrableTypeAccessStack.push(() -> getTypeConfiguration().getBasicTypeForJavaType(Integer.class));
        sqlQueryPart.setOffsetClauseExpression(visitOffsetExpression(sqmQueryPart.getOffsetExpression()));
        if (sqmQueryPart.getFetchClauseType() == FetchClauseType.PERCENT_ONLY || sqmQueryPart.getFetchClauseType() == FetchClauseType.PERCENT_WITH_TIES) {
            inferrableTypeAccessStack.pop();
            inferrableTypeAccessStack.push(() -> getTypeConfiguration().getBasicTypeForJavaType(Double.class));
        }
        sqlQueryPart.setFetchClauseExpression(visitFetchExpression(sqmQueryPart.getFetchExpression()), sqmQueryPart.getFetchClauseType());
        inferrableTypeAccessStack.pop();
    }
}
Also used : BigInteger(java.math.BigInteger) SqmSortSpecification(org.hibernate.query.sqm.tree.select.SqmSortSpecification) SortSpecification(org.hibernate.sql.ast.tree.select.SortSpecification) SqmSortSpecification(org.hibernate.query.sqm.tree.select.SqmSortSpecification)

Example 5 with SqmSortSpecification

use of org.hibernate.query.sqm.tree.select.SqmSortSpecification in project hibernate-orm by hibernate.

the class HHH13884Test method testDefaultReversedOrderImpl.

@Test
public void testDefaultReversedOrderImpl() {
    SqmExpression<?> expression = mock(SqmExpression.class);
    SqmSortSpecification order = new SqmSortSpecification(expression);
    assertEquals(expression, order.getExpression());
    assertTrue("Order should be ascending by default", order.isAscending());
    Order reversed = order.reverse();
    assertEquals(expression, reversed.getExpression());
    assertFalse("Reversed Order should be descending", reversed.isAscending());
    assertNotSame("Order.reverse() should create new instance by the contract", order, reversed);
}
Also used : Order(jakarta.persistence.criteria.Order) SqmSortSpecification(org.hibernate.query.sqm.tree.select.SqmSortSpecification) Test(org.junit.Test)

Aggregations

SqmSortSpecification (org.hibernate.query.sqm.tree.select.SqmSortSpecification)11 SortSpecification (org.hibernate.sql.ast.tree.select.SortSpecification)5 SelfRenderingFunctionSqlAstExpression (org.hibernate.query.sqm.function.SelfRenderingFunctionSqlAstExpression)3 ArgumentsValidator (org.hibernate.query.sqm.produce.function.ArgumentsValidator)3 SqmExpression (org.hibernate.query.sqm.tree.expression.SqmExpression)3 SqlAstNode (org.hibernate.sql.ast.tree.SqlAstNode)3 Over (org.hibernate.sql.ast.tree.expression.Over)3 ArrayList (java.util.ArrayList)2 ParseTree (org.antlr.v4.runtime.tree.ParseTree)2 HqlParser (org.hibernate.grammars.hql.HqlParser)2 SelfRenderingOrderedSetAggregateFunctionSqlAstExpression (org.hibernate.query.sqm.function.SelfRenderingOrderedSetAggregateFunctionSqlAstExpression)2 SqmToSqlAstConverter (org.hibernate.query.sqm.sql.SqmToSqlAstConverter)2 SqmOver (org.hibernate.query.sqm.tree.expression.SqmOver)2 SqmPredicate (org.hibernate.query.sqm.tree.predicate.SqmPredicate)2 SqmOrderByClause (org.hibernate.query.sqm.tree.select.SqmOrderByClause)2 Clause (org.hibernate.sql.ast.Clause)2 Predicate (org.hibernate.sql.ast.tree.predicate.Predicate)2 Test (org.junit.Test)2 Order (jakarta.persistence.criteria.Order)1 BigInteger (java.math.BigInteger)1