Search in sources :

Example 1 with SqmAliasedNodeRef

use of org.hibernate.query.sqm.tree.expression.SqmAliasedNodeRef in project hibernate-orm by hibernate.

the class SemanticQueryBuilder method resolveOrderByOrGroupByExpression.

private SqmExpression<?> resolveOrderByOrGroupByExpression(ParseTree child, boolean definedCollate) {
    if (child instanceof TerminalNode) {
        if (definedCollate) {
            // This is syntactically disallowed
            throw new ParsingException("COLLATE is not allowed for position based order-by or group-by items");
        }
        final int position = Integer.parseInt(child.getText());
        // make sure this selection exists
        final SqmAliasedNode<?> nodeByPosition = getCurrentProcessingState().getPathRegistry().findAliasedNodeByPosition(position);
        if (nodeByPosition == null) {
            throw new ParsingException("Numeric literal '" + position + "' used in group-by does not match a registered select-item");
        }
        return new SqmAliasedNodeRef(position, integerDomainType, creationContext.getNodeBuilder());
    } else if (child instanceof HqlParser.IdentifierContext) {
        final String identifierText = visitIdentifier((HqlParser.IdentifierContext) child);
        final Integer correspondingPosition = getCurrentProcessingState().getPathRegistry().findAliasedNodePosition(identifierText);
        if (correspondingPosition != null) {
            if (definedCollate) {
                // This is syntactically disallowed
                throw new ParsingException("COLLATE is not allowed for alias based order-by or group-by items");
            }
            return new SqmAliasedNodeRef(correspondingPosition, integerDomainType, creationContext.getNodeBuilder());
        }
        final SqmFrom<?, ?> sqmFrom = getCurrentProcessingState().getPathRegistry().findFromByAlias(identifierText, true);
        if (sqmFrom != null) {
            if (definedCollate) {
                // This is syntactically disallowed
                throw new ParsingException("COLLATE is not allowed for alias based order-by or group-by items");
            }
            // this will group-by all of the sub-parts in the from-element's model part
            return sqmFrom;
        }
        final DotIdentifierConsumer dotIdentifierConsumer = dotIdentifierConsumerStack.getCurrent();
        dotIdentifierConsumer.consumeIdentifier(identifierText, true, true);
        return (SqmExpression<?>) dotIdentifierConsumer.getConsumedPart();
    }
    return (SqmExpression<?>) child.accept(this);
}
Also used : SqmAliasedNodeRef(org.hibernate.query.sqm.tree.expression.SqmAliasedNodeRef) SqmFrom(org.hibernate.query.sqm.tree.from.SqmFrom) AbstractSqmFrom(org.hibernate.query.sqm.tree.domain.AbstractSqmFrom) BigInteger(java.math.BigInteger) SqmExpression(org.hibernate.query.sqm.tree.expression.SqmExpression) ParsingException(org.hibernate.query.sqm.ParsingException) HqlParser(org.hibernate.grammars.hql.HqlParser) DotIdentifierConsumer(org.hibernate.query.hql.spi.DotIdentifierConsumer) TerminalNode(org.antlr.v4.runtime.tree.TerminalNode)

Example 2 with SqmAliasedNodeRef

use of org.hibernate.query.sqm.tree.expression.SqmAliasedNodeRef 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)

Aggregations

BigInteger (java.math.BigInteger)2 SqmAliasedNodeRef (org.hibernate.query.sqm.tree.expression.SqmAliasedNodeRef)2 SqmExpression (org.hibernate.query.sqm.tree.expression.SqmExpression)2 ArrayList (java.util.ArrayList)1 TerminalNode (org.antlr.v4.runtime.tree.TerminalNode)1 HqlParser (org.hibernate.grammars.hql.HqlParser)1 DotIdentifierConsumer (org.hibernate.query.hql.spi.DotIdentifierConsumer)1 ParsingException (org.hibernate.query.sqm.ParsingException)1 SelfRenderingAggregateFunctionSqlAstExpression (org.hibernate.query.sqm.function.SelfRenderingAggregateFunctionSqlAstExpression)1 SelfRenderingFunctionSqlAstExpression (org.hibernate.query.sqm.function.SelfRenderingFunctionSqlAstExpression)1 AbstractSqmFrom (org.hibernate.query.sqm.tree.domain.AbstractSqmFrom)1 SqmModifiedSubQueryExpression (org.hibernate.query.sqm.tree.expression.SqmModifiedSubQueryExpression)1 SqmFrom (org.hibernate.query.sqm.tree.from.SqmFrom)1 SqmQuerySpec (org.hibernate.query.sqm.tree.select.SqmQuerySpec)1 SqlSelection (org.hibernate.sql.ast.spi.SqlSelection)1 BinaryArithmeticExpression (org.hibernate.sql.ast.tree.expression.BinaryArithmeticExpression)1 CaseSearchedExpression (org.hibernate.sql.ast.tree.expression.CaseSearchedExpression)1 CaseSimpleExpression (org.hibernate.sql.ast.tree.expression.CaseSimpleExpression)1 ConvertedQueryLiteral (org.hibernate.sql.ast.tree.expression.ConvertedQueryLiteral)1 Expression (org.hibernate.sql.ast.tree.expression.Expression)1