Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
package org.hibernate.query.range;

import jakarta.persistence.criteria.CriteriaBuilder;
import jakarta.persistence.criteria.Expression;
import jakarta.persistence.criteria.Path;
import jakarta.persistence.criteria.Predicate;

Expand All @@ -24,14 +23,9 @@ record CaseInsensitiveValue(String value) implements Range<String> {

@Override
public Predicate toPredicate(Path<? extends String> path, CriteriaBuilder builder) {
// TODO: it would be much better to not do use literal,
// and let it be treated as a parameter, but we
// we run into the usual bug with parameters in
// manipulated SQM trees
@SuppressWarnings("unchecked")
final Path<String> stringPath = (Path<String>) path; // safe, because String is final
final Expression<String> literal = builder.literal( value.toLowerCase( Locale.ROOT ) );
return builder.lower( stringPath ).equalTo( literal );
return builder.lower( stringPath ).equalTo( value.toLowerCase( Locale.ROOT ) );
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
package org.hibernate.query.range;

import jakarta.persistence.criteria.CriteriaBuilder;
import jakarta.persistence.criteria.Expression;
import jakarta.persistence.criteria.Path;
import jakarta.persistence.criteria.Predicate;
import org.hibernate.internal.util.ReflectHelper;
Expand All @@ -24,14 +23,9 @@ record LowerBound<U extends Comparable<U>>(U bound, boolean open) implements Ran

@Override
public Predicate toPredicate(Path<? extends U> path, CriteriaBuilder builder) {
// TODO: it would be much better to not do use literal,
// and let it be treated as a parameter, but we
// we run into the usual bug with parameters in
// manipulated SQM trees
final Expression<U> literal = builder.literal( bound );
return open
? builder.greaterThan( path, literal )
: builder.greaterThanOrEqualTo( path, literal );
? builder.greaterThan( path, bound )
: builder.greaterThanOrEqualTo( path, bound );
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
package org.hibernate.query.range;

import jakarta.persistence.criteria.CriteriaBuilder;
import jakarta.persistence.criteria.Expression;
import jakarta.persistence.criteria.Path;
import jakarta.persistence.criteria.Predicate;

Expand All @@ -23,14 +22,9 @@ record UpperBound<U extends Comparable<U>>(U bound, boolean open) implements Ran

@Override
public Predicate toPredicate(Path<? extends U> path, CriteriaBuilder builder) {
// TODO: it would be much better to not do use literal,
// and let it be treated as a parameter, but we
// we run into the usual bug with parameters in
// manipulated SQM trees
final Expression<U> literal = builder.literal( bound );
return open
? builder.lessThan( path, literal )
: builder.lessThanOrEqualTo( path, literal );
? builder.lessThan( path, bound )
: builder.lessThanOrEqualTo( path, bound );
}

@Override @SuppressWarnings("unchecked")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
package org.hibernate.query.range;

import jakarta.persistence.criteria.CriteriaBuilder;
import jakarta.persistence.criteria.Expression;
import jakarta.persistence.criteria.Path;
import jakarta.persistence.criteria.Predicate;
import org.hibernate.internal.util.ReflectHelper;
Expand All @@ -24,12 +23,7 @@ record Value<U>(U value) implements Range<U> {

@Override
public Predicate toPredicate(Path<? extends U> path, CriteriaBuilder builder) {
// TODO: it would be much better to not do use literal,
// and let it be treated as a parameter, but we
// we run into the usual bug with parameters in
// manipulated SQM trees
final Expression<U> literal = builder.literal( value );
return path.equalTo( literal );
return path.equalTo( value );
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@
*/
package org.hibernate.query.sqm.internal;

import jakarta.persistence.TemporalType;
import org.hibernate.HibernateException;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.graph.spi.AppliedGraph;
import org.hibernate.query.BindableType;
import org.hibernate.query.IllegalSelectQueryException;
import org.hibernate.query.KeyedPage;
import org.hibernate.query.KeyedResultList;
Expand All @@ -23,9 +25,15 @@
import org.hibernate.query.spi.ParameterMetadataImplementor;
import org.hibernate.query.spi.QueryEngine;
import org.hibernate.query.spi.QueryOptions;
import org.hibernate.query.spi.QueryParameterBinding;
import org.hibernate.query.spi.QueryParameterBindings;
import org.hibernate.query.spi.SelectQueryPlan;
import org.hibernate.query.sqm.SqmQuerySource;
import org.hibernate.query.sqm.spi.NamedSqmQueryMemento;
import org.hibernate.query.sqm.tree.SqmStatement;
import org.hibernate.query.sqm.tree.expression.JpaCriteriaParameter;
import org.hibernate.query.sqm.tree.expression.SqmJpaCriteriaParameterWrapper;
import org.hibernate.query.sqm.tree.expression.SqmParameter;
import org.hibernate.query.sqm.tree.from.SqmRoot;
import org.hibernate.query.sqm.tree.select.SqmQueryGroup;
import org.hibernate.query.sqm.tree.select.SqmQueryPart;
Expand Down Expand Up @@ -118,9 +126,64 @@ private SqmSelectStatement<R> getSqmSelectStatement() {
}
}

protected void copyParameterBindings(QueryParameterBindings oldParameterBindings) {
final QueryParameterBindings parameterBindings = getQueryParameterBindings();
oldParameterBindings.visitBindings( (queryParameter, binding) -> {
if ( binding.isBound() ) {
//noinspection unchecked
final QueryParameterBinding<Object> newBinding = (QueryParameterBinding<Object>) parameterBindings.getBinding( queryParameter );
//noinspection unchecked
final BindableType<Object> bindType = (BindableType<Object>) binding.getBindType();
final TemporalType explicitTemporalPrecision = binding.getExplicitTemporalPrecision();
if ( binding.isMultiValued() ) {
if ( explicitTemporalPrecision != null ) {
newBinding.setBindValues( binding.getBindValues(), explicitTemporalPrecision, getSessionFactory().getTypeConfiguration() );
}
else if ( bindType != null ) {
newBinding.setBindValues( binding.getBindValues(), bindType );
}
else {
newBinding.setBindValues( binding.getBindValues() );
}
}
else {
if ( explicitTemporalPrecision != null ) {
newBinding.setBindValue( binding.getBindValue(), explicitTemporalPrecision );
}
else if ( bindType != null ) {
newBinding.setBindValue( binding.getBindValue(), bindType );
}
else {
newBinding.setBindValue( binding.getBindValue() );
}
}
}
} );

// Parameters might be created through HibernateCriteriaBuilder.value which we need to bind here
for ( SqmParameter<?> sqmParameter : getDomainParameterXref().getParameterResolutions().getSqmParameters() ) {
if ( sqmParameter instanceof SqmJpaCriteriaParameterWrapper<?> wrapper ) {
bindCriteriaParameter( wrapper );
}
}
}

protected <T> void bindCriteriaParameter(SqmJpaCriteriaParameterWrapper<T> sqmParameter) {
final JpaCriteriaParameter<T> criteriaParameter = sqmParameter.getJpaCriteriaParameter();
final T value = criteriaParameter.getValue();
// We don't set a null value, unless the type is also null which
// is the case when using HibernateCriteriaBuilder.value
if ( value != null || criteriaParameter.getNodeType() == null ) {
// Use the anticipated type for binding the value if possible
getQueryParameterBindings()
.getBinding( criteriaParameter )
.setBindValue( value, criteriaParameter.getAnticipatedType() );
}
}

@Override
public SelectionQuery<R> setOrder(List<? extends Order<? super R>> orderList) {
final SqmSelectStatement<R> selectStatement = getSqmSelectStatement().copy( noParamCopyContext() );
final SqmSelectStatement<R> selectStatement = getSqmSelectStatement().copy( noParamCopyContext( SqmQuerySource.CRITERIA ) );
selectStatement.orderBy( orderList.stream().map( order -> sortSpecification( selectStatement, order ) )
.collect( toList() ) );
// TODO: when the QueryInterpretationCache can handle caching criteria queries,
Expand All @@ -133,7 +196,7 @@ public SelectionQuery<R> setOrder(List<? extends Order<? super R>> orderList) {

@Override
public SelectionQuery<R> setOrder(Order<? super R> order) {
final SqmSelectStatement<R> selectStatement = getSqmSelectStatement().copy( noParamCopyContext() );
final SqmSelectStatement<R> selectStatement = getSqmSelectStatement().copy( noParamCopyContext( SqmQuerySource.CRITERIA ) );
selectStatement.orderBy( sortSpecification( selectStatement, order ) );
// TODO: when the QueryInterpretationCache can handle caching criteria queries,
// simply cache the new SQM as if it were a criteria query, and remove this:
Expand All @@ -144,7 +207,7 @@ public SelectionQuery<R> setOrder(Order<? super R> order) {

@Override
public SelectionQuery<R> addRestriction(Restriction<? super R> restriction) {
final SqmSelectStatement<R> selectStatement = getSqmSelectStatement().copy( noParamCopyContext() );
final SqmSelectStatement<R> selectStatement = getSqmSelectStatement().copy( noParamCopyContext( SqmQuerySource.CRITERIA ) );
restriction.apply( selectStatement, selectStatement.<R>getRoot( 0, getExpectedResultType() ) );
// TODO: when the QueryInterpretationCache can handle caching criteria queries,
// simply cache the new SQM as if it were a criteria query, and remove this:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,6 @@
import org.hibernate.query.sqm.tree.SqmStatement;
import org.hibernate.query.sqm.tree.delete.SqmDeleteStatement;
import org.hibernate.query.sqm.tree.domain.SqmPath;
import org.hibernate.query.sqm.tree.expression.JpaCriteriaParameter;
import org.hibernate.query.sqm.tree.expression.SqmJpaCriteriaParameterWrapper;
import org.hibernate.query.sqm.tree.expression.SqmParameter;
import org.hibernate.query.sqm.tree.from.SqmRoot;
Expand Down Expand Up @@ -121,13 +120,13 @@ public class QuerySqmImpl<R>
implements SqmQueryImplementor<R>, InterpretationsKeySource, DomainQueryExecutionContext {

private final String hql;
private final Object queryStringCacheKey;
private Object queryStringCacheKey;
private SqmStatement<R> sqm;

private final ParameterMetadataImplementor parameterMetadata;
private final DomainParameterXref domainParameterXref;
private ParameterMetadataImplementor parameterMetadata;
private DomainParameterXref domainParameterXref;

private final QueryParameterBindings parameterBindings;
private QueryParameterBindings parameterBindings;

private final Class<R> resultType;
private final TupleMetadata tupleMetadata;
Expand Down Expand Up @@ -254,18 +253,6 @@ else if ( sqm instanceof AbstractSqmDmlStatement<R> update ) {
tupleMetadata = buildTupleMetadata( criteria, expectedResultType );
}

private <T> void bindCriteriaParameter(SqmJpaCriteriaParameterWrapper<T> sqmParameter) {
final JpaCriteriaParameter<T> jpaCriteriaParameter = sqmParameter.getJpaCriteriaParameter();
final T value = jpaCriteriaParameter.getValue();
// We don't set a null value, unless the type is also null which
// is the case when using HibernateCriteriaBuilder.value
if ( value != null || jpaCriteriaParameter.getNodeType() == null ) {
// Use the anticipated type for binding the value if possible
getQueryParameterBindings().getBinding( jpaCriteriaParameter )
.setBindValue( value, jpaCriteriaParameter.getAnticipatedType() );
}
}

@Override
public TupleMetadata getTupleMetadata() {
return tupleMetadata;
Expand All @@ -289,6 +276,15 @@ public SqmStatement<R> getSqmStatement() {
@Override
protected void setSqmStatement(SqmSelectStatement<R> sqm) {
this.sqm = sqm;
this.queryStringCacheKey = sqm;

final QueryParameterBindings oldParameterBindings = parameterBindings;
domainParameterXref = DomainParameterXref.from( sqm );
parameterMetadata = !domainParameterXref.hasParameters()
? ParameterMetadataImpl.EMPTY
: new ParameterMetadataImpl( domainParameterXref.getQueryParameters() );
parameterBindings = parameterMetadata.createBindings( getSessionFactory() );
copyParameterBindings( oldParameterBindings );
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@
import org.hibernate.query.sqm.internal.SqmInterpretationsKey.InterpretationsKeySource;
import org.hibernate.query.sqm.spi.SqmSelectionQueryImplementor;
import org.hibernate.query.sqm.tree.SqmCopyContext;
import org.hibernate.query.sqm.tree.expression.JpaCriteriaParameter;
import org.hibernate.query.sqm.tree.expression.SqmJpaCriteriaParameterWrapper;
import org.hibernate.query.sqm.tree.expression.SqmParameter;
import org.hibernate.query.sqm.tree.select.SqmQueryPart;
Expand Down Expand Up @@ -89,12 +88,12 @@
public class SqmSelectionQueryImpl<R> extends AbstractSqmSelectionQuery<R>
implements SqmSelectionQueryImplementor<R>, InterpretationsKeySource {
private final String hql;
private final Object queryStringCacheKey;
private Object queryStringCacheKey;
private SqmSelectStatement<R> sqm;

private final ParameterMetadataImplementor parameterMetadata;
private final DomainParameterXref domainParameterXref;
private final QueryParameterBindings parameterBindings;
private ParameterMetadataImplementor parameterMetadata;
private DomainParameterXref domainParameterXref;
private QueryParameterBindings parameterBindings;

private final Class<R> expectedResultType;
private final Class<?> resultType;
Expand Down Expand Up @@ -330,19 +329,6 @@ else if ( expectedResultType != null ) {
}
}

private <T> void bindCriteriaParameter(SqmJpaCriteriaParameterWrapper<T> sqmParameter) {
final JpaCriteriaParameter<T> criteriaParameter = sqmParameter.getJpaCriteriaParameter();
final T value = criteriaParameter.getValue();
// We don't set a null value, unless the type is also null which
// is the case when using HibernateCriteriaBuilder.value
if ( value != null || criteriaParameter.getNodeType() == null ) {
// Use the anticipated type for binding the value if possible
getQueryParameterBindings()
.getBinding( criteriaParameter )
.setBindValue( value, criteriaParameter.getAnticipatedType() );
}
}

@Override
public TupleMetadata getTupleMetadata() {
return tupleMetadata;
Expand All @@ -356,6 +342,15 @@ public SqmSelectStatement<R> getSqmStatement() {
@Override
protected void setSqmStatement(SqmSelectStatement<R> sqm) {
this.sqm = sqm;
this.queryStringCacheKey = sqm;

final QueryParameterBindings oldParameterBindings = parameterBindings;
domainParameterXref = DomainParameterXref.from( sqm );
parameterMetadata = !domainParameterXref.hasParameters()
? ParameterMetadataImpl.EMPTY
: new ParameterMetadataImpl( domainParameterXref.getQueryParameters() );
parameterBindings = parameterMetadata.createBindings( getSessionFactory() );
copyParameterBindings( oldParameterBindings );
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import org.hibernate.query.sqm.tree.SqmVisitableNode;
import org.hibernate.query.sqm.tree.domain.SqmIndexedCollectionAccessPath;
import org.hibernate.query.sqm.tree.expression.JpaCriteriaParameter;
import org.hibernate.query.sqm.tree.expression.SqmAliasedNodeRef;
import org.hibernate.query.sqm.tree.expression.SqmCaseSearched;
import org.hibernate.query.sqm.tree.expression.SqmCaseSimple;
import org.hibernate.query.sqm.tree.expression.SqmExpression;
Expand All @@ -37,6 +38,7 @@
import org.hibernate.query.sqm.tree.predicate.SqmNullnessPredicate;
import org.hibernate.query.sqm.tree.predicate.SqmTruthnessPredicate;
import org.hibernate.query.sqm.tree.select.SqmSelectStatement;
import org.hibernate.query.sqm.tree.select.SqmSortSpecification;

/**
* @author Steve Ebersole
Expand Down Expand Up @@ -341,4 +343,15 @@ public Object visitInSubQueryPredicate(SqmInSubQueryPredicate<?> predicate) {
withTypeInference( predicate.getTestExpression(), predicate.getSubQueryExpression() );
return predicate;
}

@Override
public Object visitSortSpecification(SqmSortSpecification sortSpecification) {
if ( sortSpecification.getSortExpression() instanceof SqmAliasedNodeRef ) {
// Ignore aliases
return sortSpecification;
}
else {
return super.visitSortSpecification( sortSpecification );
}
}
}