Search in sources :

Example 1 with JdbcMappingContainer

use of org.hibernate.metamodel.mapping.JdbcMappingContainer in project hibernate-orm by hibernate.

the class CountFunction method canReplaceWithStar.

private boolean canReplaceWithStar(SqlAstNode arg, SqlAstTranslator<?> translator) {
    // To determine if we can replace the argument with a star, we must know if the argument is nullable
    if (arg instanceof AbstractSqmPathInterpretation<?>) {
        final AbstractSqmPathInterpretation<?> pathInterpretation = (AbstractSqmPathInterpretation<?>) arg;
        final TableGroup tableGroup = pathInterpretation.getTableGroup();
        final Expression sqlExpression = pathInterpretation.getSqlExpression();
        final JdbcMappingContainer expressionType = sqlExpression.getExpressionType();
        // The entity identifier mapping is always considered non-nullable
        final boolean isNonNullable = expressionType instanceof EntityIdentifierMapping;
        // But we also have to check if it contains joins that could alter the nullability (RIGHT or FULL)
        if (isNonNullable && tableGroup.canUseInnerJoins() && !hasJoinsAlteringNullability(tableGroup)) {
            // COUNT can only be used in query specs as query groups can only refer positionally in the order by
            final QuerySpec querySpec = (QuerySpec) translator.getCurrentQueryPart();
            // On top of this, we also have to ensure that there are no neighbouring joins that alter nullability
            for (TableGroup root : querySpec.getFromClause().getRoots()) {
                final Boolean result = hasNeighbouringJoinsAlteringNullability(root, tableGroup);
                if (result != null) {
                    return !result;
                }
            }
            return true;
        }
    }
    return false;
}
Also used : JdbcMappingContainer(org.hibernate.metamodel.mapping.JdbcMappingContainer) AbstractSqmPathInterpretation(org.hibernate.query.sqm.sql.internal.AbstractSqmPathInterpretation) TableGroup(org.hibernate.sql.ast.tree.from.TableGroup) Expression(org.hibernate.sql.ast.tree.expression.Expression) FunctionExpression(org.hibernate.sql.ast.tree.expression.FunctionExpression) EntityIdentifierMapping(org.hibernate.metamodel.mapping.EntityIdentifierMapping) QuerySpec(org.hibernate.sql.ast.tree.select.QuerySpec)

Example 2 with JdbcMappingContainer

use of org.hibernate.metamodel.mapping.JdbcMappingContainer in project hibernate-orm by hibernate.

the class AnsiTrimEmulationFunctionTest method render.

private String render(Dialect dialect, TrimFunction function, TrimSpec trimSpec, char trimCharacter, String trimSource) {
    SessionFactoryImplementor factory = Mockito.mock(SessionFactoryImplementor.class);
    JdbcServices jdbcServices = Mockito.mock(JdbcServices.class);
    Mockito.doReturn(jdbcServices).when(factory).getJdbcServices();
    Mockito.doReturn(dialect).when(jdbcServices).getDialect();
    StandardSqlAstTranslator<JdbcOperation> walker = new StandardSqlAstTranslator<>(factory, null);
    List<SqlAstNode> sqlAstArguments = new ArrayList<>();
    sqlAstArguments.add(new TrimSpecification(trimSpec));
    sqlAstArguments.add(new QueryLiteral<>(trimCharacter, new BasicTypeImpl<>(CharacterJavaType.INSTANCE, CharJdbcType.INSTANCE)));
    sqlAstArguments.add(new SelfRenderingExpression() {

        @Override
        public void renderToSql(SqlAppender sqlAppender, SqlAstTranslator<?> walker, SessionFactoryImplementor sessionFactory) {
            sqlAppender.appendSql(trimSource);
        }

        @Override
        public JdbcMappingContainer getExpressionType() {
            return null;
        }
    });
    function.render(walker, sqlAstArguments, walker);
    return walker.getSql();
}
Also used : SqlAppender(org.hibernate.sql.ast.spi.SqlAppender) SessionFactoryImplementor(org.hibernate.engine.spi.SessionFactoryImplementor) BasicTypeImpl(org.hibernate.type.internal.BasicTypeImpl) JdbcOperation(org.hibernate.sql.exec.spi.JdbcOperation) ArrayList(java.util.ArrayList) TrimSpecification(org.hibernate.sql.ast.tree.expression.TrimSpecification) JdbcServices(org.hibernate.engine.jdbc.spi.JdbcServices) SqlAstNode(org.hibernate.sql.ast.tree.SqlAstNode) JdbcMappingContainer(org.hibernate.metamodel.mapping.JdbcMappingContainer) SelfRenderingExpression(org.hibernate.sql.ast.tree.expression.SelfRenderingExpression) StandardSqlAstTranslator(org.hibernate.sql.ast.spi.StandardSqlAstTranslator)

Example 3 with JdbcMappingContainer

use of org.hibernate.metamodel.mapping.JdbcMappingContainer in project hibernate-orm by hibernate.

the class SmokeTests method testConvertedHqlInterpretation.

@Test
public void testConvertedHqlInterpretation(SessionFactoryScope scope) {
    scope.inTransaction(session -> {
        final JdbcTypeRegistry jdbcTypeRegistry = session.getFactory().getTypeConfiguration().getJdbcTypeRegistry();
        final QueryImplementor<Gender> query = session.createQuery("select e.gender from SimpleEntity e", Gender.class);
        final SqmQueryImplementor<Gender> hqlQuery = (SqmQueryImplementor<Gender>) query;
        final SqmSelectStatement<Gender> sqmStatement = (SqmSelectStatement<Gender>) hqlQuery.getSqmStatement();
        final StandardSqmTranslator<SelectStatement> sqmConverter = new StandardSqmTranslator<>(sqmStatement, hqlQuery.getQueryOptions(), ((QuerySqmImpl<?>) hqlQuery).getDomainParameterXref(), query.getParameterBindings(), session.getLoadQueryInfluencers(), scope.getSessionFactory(), true);
        final SqmTranslation<SelectStatement> sqmInterpretation = sqmConverter.translate();
        final SelectStatement sqlAst = sqmInterpretation.getSqlAst();
        final FromClause fromClause = sqlAst.getQuerySpec().getFromClause();
        assertThat(fromClause.getRoots().size(), is(1));
        final TableGroup rootTableGroup = fromClause.getRoots().get(0);
        assertThat(rootTableGroup.getPrimaryTableReference(), notNullValue());
        assertThat(rootTableGroup.getPrimaryTableReference().getTableId(), is("mapping_simple_entity"));
        assertThat(rootTableGroup.getTableReferenceJoins().size(), is(0));
        assertThat(rootTableGroup.getTableGroupJoins().isEmpty(), is(true));
        // `s` is the "alias stem" for `SimpleEntity` and as it is the first entity with that stem in
        // the query the base becomes `s1`.  The primary table reference is always suffixed as `_0`
        assertThat(rootTableGroup.getPrimaryTableReference().getIdentificationVariable(), is("s1_0"));
        final SelectClause selectClause = sqlAst.getQuerySpec().getSelectClause();
        assertThat(selectClause.getSqlSelections().size(), is(1));
        final SqlSelection sqlSelection = selectClause.getSqlSelections().get(0);
        assertThat(sqlSelection.getJdbcResultSetIndex(), is(1));
        assertThat(sqlSelection.getValuesArrayPosition(), is(0));
        assertThat(sqlSelection.getJdbcValueExtractor(), notNullValue());
        assertThat(sqlSelection, instanceOf(SqlSelectionImpl.class));
        final Expression selectedExpression = sqlSelection.getExpression();
        assertThat(selectedExpression, instanceOf(ColumnReference.class));
        final ColumnReference columnReference = (ColumnReference) selectedExpression;
        assertThat(columnReference.renderSqlFragment(scope.getSessionFactory()), is("s1_0.gender"));
        final JdbcMappingContainer selectedExpressible = selectedExpression.getExpressionType();
        assertThat(selectedExpressible, instanceOf(BasicTypeImpl.class));
        final BasicTypeImpl<?> basicType = (BasicTypeImpl<?>) selectedExpressible;
        assertThat(basicType.getJavaTypeDescriptor().getJavaTypeClass(), AssignableMatcher.assignableTo(Integer.class));
        assertThat(basicType.getJdbcType(), is(jdbcTypeRegistry.getDescriptor(Types.TINYINT)));
        assertThat(sqlAst.getDomainResultDescriptors().size(), is(1));
        final DomainResult<?> domainResult = sqlAst.getDomainResultDescriptors().get(0);
        assertThat(domainResult, instanceOf(BasicResult.class));
        final BasicResult<?> scalarDomainResult = (BasicResult<?>) domainResult;
        assertThat(scalarDomainResult.getAssembler(), instanceOf(BasicResultAssembler.class));
        final BasicResultAssembler<?> assembler = (BasicResultAssembler<?>) scalarDomainResult.getAssembler();
        assertThat(assembler.getValueConverter(), notNullValue());
        assertThat(assembler.getValueConverter(), instanceOf(OrdinalEnumValueConverter.class));
        final NavigablePath expectedSelectedPath = new NavigablePath(SimpleEntity.class.getName(), "e").append("gender");
        assertThat(domainResult.getNavigablePath(), equalTo(expectedSelectedPath));
        assertThat(domainResult, instanceOf(BasicResult.class));
        // ScalarDomainResultImpl creates and caches the assembler at its creation.
        // this just gets access to that cached one
        final DomainResultAssembler<?> resultAssembler = domainResult.createResultAssembler(null, null);
        assertThat(resultAssembler, instanceOf(BasicResultAssembler.class));
        final BasicValueConverter<?, ?> valueConverter = ((BasicResultAssembler<?>) resultAssembler).getValueConverter();
        assertThat(valueConverter, notNullValue());
        assertThat(valueConverter, instanceOf(OrdinalEnumValueConverter.class));
        final JdbcSelect jdbcSelectOperation = new StandardSqlAstTranslator<JdbcSelect>(session.getSessionFactory(), sqlAst).translate(null, QueryOptions.NONE);
        assertThat(jdbcSelectOperation.getSql(), is("select s1_0.gender from mapping_simple_entity s1_0"));
    });
}
Also used : SelectClause(org.hibernate.sql.ast.tree.select.SelectClause) NavigablePath(org.hibernate.query.spi.NavigablePath) BasicTypeImpl(org.hibernate.type.internal.BasicTypeImpl) Gender(org.hibernate.orm.test.mapping.SmokeTests.Gender) SqlSelection(org.hibernate.sql.ast.spi.SqlSelection) SqmSelectStatement(org.hibernate.query.sqm.tree.select.SqmSelectStatement) SelectStatement(org.hibernate.sql.ast.tree.select.SelectStatement) JdbcMappingContainer(org.hibernate.metamodel.mapping.JdbcMappingContainer) SqmQueryImplementor(org.hibernate.query.hql.spi.SqmQueryImplementor) BasicResult(org.hibernate.sql.results.graph.basic.BasicResult) OrdinalEnumValueConverter(org.hibernate.metamodel.model.convert.internal.OrdinalEnumValueConverter) SqmSelectStatement(org.hibernate.query.sqm.tree.select.SqmSelectStatement) JdbcSelect(org.hibernate.sql.exec.spi.JdbcSelect) TableGroup(org.hibernate.sql.ast.tree.from.TableGroup) BasicResultAssembler(org.hibernate.sql.results.graph.basic.BasicResultAssembler) FromClause(org.hibernate.sql.ast.tree.from.FromClause) Expression(org.hibernate.sql.ast.tree.expression.Expression) SqlSelectionImpl(org.hibernate.sql.results.internal.SqlSelectionImpl) StandardSqmTranslator(org.hibernate.query.sqm.sql.internal.StandardSqmTranslator) JdbcTypeRegistry(org.hibernate.type.descriptor.jdbc.spi.JdbcTypeRegistry) ColumnReference(org.hibernate.sql.ast.tree.expression.ColumnReference) Test(org.junit.jupiter.api.Test)

Example 4 with JdbcMappingContainer

use of org.hibernate.metamodel.mapping.JdbcMappingContainer in project hibernate-orm by hibernate.

the class BaseSqmToSqlAstConverter method transformDurationArithmetic.

private Object transformDurationArithmetic(SqmBinaryArithmetic<?> expression) {
    BinaryArithmeticOperator operator = expression.getOperator();
    // the expression tree
    switch(operator) {
        case ADD:
        case SUBTRACT:
            // the only legal binary operations involving
            // a duration with a date or timestamp are
            // addition and subtraction with the duration
            // on the right and the date or timestamp on
            // the left, producing a date or timestamp
            // 
            // ts + d or ts - d
            // 
            // the only legal binary operations involving
            // two durations are addition and subtraction,
            // producing a duration
            // 
            // d1 + d2
            // re-express addition of non-leaf duration
            // expressions to a date or timestamp as
            // addition of leaf durations to a date or
            // timestamp
            // ts + x * (d1 + d2) => (ts + x * d1) + x * d2
            // ts - x * (d1 + d2) => (ts - x * d1) - x * d2
            // ts + x * (d1 - d2) => (ts + x * d1) - x * d2
            // ts - x * (d1 - d2) => (ts - x * d1) + x * d2
            Expression timestamp = adjustedTimestamp;
            SqmExpressible<?> timestampType = adjustedTimestampType;
            adjustedTimestamp = toSqlExpression(expression.getLeftHandOperand().accept(this));
            JdbcMappingContainer type = adjustedTimestamp.getExpressionType();
            if (type instanceof SqmExpressible) {
                adjustedTimestampType = (SqmExpressible<?>) type;
            } else if (type instanceof AttributeMapping) {
                adjustedTimestampType = (SqmExpressible<?>) ((AttributeMapping) type).getMappedType();
            } else {
                // else we know it has not been transformed
                adjustedTimestampType = expression.getLeftHandOperand().getNodeType();
            }
            if (operator == SUBTRACT) {
                negativeAdjustment = !negativeAdjustment;
            }
            try {
                return expression.getRightHandOperand().accept(this);
            } finally {
                if (operator == SUBTRACT) {
                    negativeAdjustment = !negativeAdjustment;
                }
                adjustedTimestamp = timestamp;
                adjustedTimestampType = timestampType;
            }
        case MULTIPLY:
            // finally, we can multiply a duration on the
            // right by a scalar value on the left
            // scalar multiplication produces a duration
            // x * d
            // distribute scalar multiplication over the
            // terms, not forgetting the propagated scale
            // x * (d1 + d2) => x * d1 + x * d2
            // x * (d1 - d2) => x * d1 - x * d2
            // -x * (d1 + d2) => - x * d1 - x * d2
            // -x * (d1 - d2) => - x * d1 + x * d2
            Expression duration = toSqlExpression(expression.getLeftHandOperand().accept(this));
            Expression scale = adjustmentScale;
            boolean negate = negativeAdjustment;
            adjustmentScale = applyScale(duration);
            // was sucked into the scale
            negativeAdjustment = false;
            try {
                return expression.getRightHandOperand().accept(this);
            } finally {
                adjustmentScale = scale;
                negativeAdjustment = negate;
            }
        default:
            throw new SemanticException("illegal operator for a duration " + operator);
    }
}
Also used : JdbcMappingContainer(org.hibernate.metamodel.mapping.JdbcMappingContainer) SqmExpressible(org.hibernate.query.sqm.SqmExpressible) 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) BinaryArithmeticOperator(org.hibernate.query.sqm.BinaryArithmeticOperator) PluralAttributeMapping(org.hibernate.metamodel.mapping.PluralAttributeMapping) ToOneAttributeMapping(org.hibernate.metamodel.mapping.internal.ToOneAttributeMapping) AttributeMapping(org.hibernate.metamodel.mapping.AttributeMapping) SemanticException(org.hibernate.query.SemanticException)

Example 5 with JdbcMappingContainer

use of org.hibernate.metamodel.mapping.JdbcMappingContainer in project hibernate-orm by hibernate.

the class BaseSqmToSqlAstConverter method visitBasicValuedPath.

// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// SqmPath
@Override
public Expression visitBasicValuedPath(SqmBasicValuedSimplePath<?> sqmPath) {
    final BasicValuedPathInterpretation<?> path = prepareReusablePath(sqmPath, () -> BasicValuedPathInterpretation.from(sqmPath, this, this, jpaQueryComplianceEnabled));
    Expression result = path;
    if (isDuration(sqmPath.getNodeType())) {
        // Durations are stored (at least by default)
        // in a NUMERIC column in seconds with fractional
        // seconds in the decimal places
        // which we need to convert to the given unit
        // 
        // This does not work at all for a Duration
        // mapped to a VARCHAR column, in which case
        // we would need to parse the weird format
        // defined by java.time.Duration (a bit hard
        // to do without some custom function).
        // Nor does it work for databases which have
        // a well-defined INTERVAL type, but that is
        // something we could implement.
        // first let's apply the propagated scale
        Expression scaledExpression = applyScale(toSqlExpression(path));
        if (adjustedTimestamp != null) {
            if (appliedByUnit != null) {
                throw new IllegalStateException();
            }
            // we're adding this variable duration to the
            // given date or timestamp, producing an
            // adjusted date or timestamp
            result = timestampadd().expression((ReturnableType<?>) adjustedTimestampType, new DurationUnit(SECOND, basicType(Long.class)), scaledExpression, adjustedTimestamp);
        } else if (appliedByUnit != null) {
            // we're applying the 'by unit' operator,
            // producing a literal scalar value, so
            // we must convert this duration from
            // nanoseconds to the given unit
            JdbcMappingContainer durationType = scaledExpression.getExpressionType();
            Duration duration;
            if (durationType.getJdbcMappings().get(0).getJdbcType().isInterval()) {
                // For interval types, we need to extract the epoch for integer arithmetic for the 'by unit' operator
                duration = new Duration(extractEpoch(scaledExpression), SECOND, (BasicValuedMapping) durationType);
            } else {
                // The absolute value of the expression is in seconds
                // as the fractional seconds are in the fraction part as can be seen in DurationJavaType
                duration = new Duration(scaledExpression, SECOND, (BasicValuedMapping) durationType);
            }
            TemporalUnit appliedUnit = appliedByUnit.getUnit().getUnit();
            BasicValuedMapping scalarType = (BasicValuedMapping) appliedByUnit.getNodeType();
            result = new Conversion(duration, appliedUnit, scalarType);
        } else {
            // a "bare" Duration value in nanoseconds
            result = scaledExpression;
        }
    }
    return withTreatRestriction(result, sqmPath);
}
Also used : ReturnableType(org.hibernate.query.ReturnableType) BasicValuedMapping(org.hibernate.metamodel.mapping.BasicValuedMapping) JdbcMappingContainer(org.hibernate.metamodel.mapping.JdbcMappingContainer) 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) TemporalUnit(org.hibernate.query.sqm.TemporalUnit) SqmDurationUnit(org.hibernate.query.sqm.tree.expression.SqmDurationUnit) DurationUnit(org.hibernate.sql.ast.tree.expression.DurationUnit) SqmToDuration(org.hibernate.query.sqm.tree.expression.SqmToDuration) Duration(org.hibernate.sql.ast.tree.expression.Duration) TypeConfiguration.isDuration(org.hibernate.type.spi.TypeConfiguration.isDuration) Conversion(org.hibernate.query.sqm.tree.expression.Conversion)

Aggregations

JdbcMappingContainer (org.hibernate.metamodel.mapping.JdbcMappingContainer)7 Expression (org.hibernate.sql.ast.tree.expression.Expression)6 SqlAstNode (org.hibernate.sql.ast.tree.SqlAstNode)3 SelfRenderingExpression (org.hibernate.sql.ast.tree.expression.SelfRenderingExpression)3 BasicValuedMapping (org.hibernate.metamodel.mapping.BasicValuedMapping)2 SelfRenderingAggregateFunctionSqlAstExpression (org.hibernate.query.sqm.function.SelfRenderingAggregateFunctionSqlAstExpression)2 SelfRenderingFunctionSqlAstExpression (org.hibernate.query.sqm.function.SelfRenderingFunctionSqlAstExpression)2 SqmExpression (org.hibernate.query.sqm.tree.expression.SqmExpression)2 SqmModifiedSubQueryExpression (org.hibernate.query.sqm.tree.expression.SqmModifiedSubQueryExpression)2 BinaryArithmeticExpression (org.hibernate.sql.ast.tree.expression.BinaryArithmeticExpression)2 CaseSearchedExpression (org.hibernate.sql.ast.tree.expression.CaseSearchedExpression)2 CaseSimpleExpression (org.hibernate.sql.ast.tree.expression.CaseSimpleExpression)2 ModifiedSubQueryExpression (org.hibernate.sql.ast.tree.expression.ModifiedSubQueryExpression)2 SelfRenderingSqlFragmentExpression (org.hibernate.sql.ast.tree.expression.SelfRenderingSqlFragmentExpression)2 SqlSelectionExpression (org.hibernate.sql.ast.tree.expression.SqlSelectionExpression)2 TableGroup (org.hibernate.sql.ast.tree.from.TableGroup)2 BasicTypeImpl (org.hibernate.type.internal.BasicTypeImpl)2 ArrayList (java.util.ArrayList)1 QueryException (org.hibernate.QueryException)1 JdbcServices (org.hibernate.engine.jdbc.spi.JdbcServices)1